[Bf-blender-cvs] [20eb199] strand_gpu: Fragment shader emulation of the current particle hair shading method.

Lukas Tönne noreply at git.blender.org
Thu Jul 7 09:38:40 CEST 2016


Commit: 20eb1992851fcf01be5c31866c902dc11d9c1196
Author: Lukas Tönne
Date:   Thu Jul 7 09:30:32 2016 +0200
Branches: strand_gpu
https://developer.blender.org/rB20eb1992851fcf01be5c31866c902dc11d9c1196

Fragment shader emulation of the current particle hair shading method.

This is a terrible shading method, using the curve tangent as a "normal" vector.
With the old particle hair this was a compromise, because line drawing does not
support nicer shading in the fixed-function pipeline. With GLSL shaders this
is just a quick starting point, and useful for comparison with the old shading.

===================================================================

M	source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
M	source/blender/gpu/shaders/gpu_shader_strand_geom.glsl

===================================================================

diff --git a/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl b/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
index 164320b..510dd1d 100644
--- a/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
@@ -1,8 +1,75 @@
+#define NUM_LIGHTS 3
+
+in vec3 fPosition;
+in vec3 fTangent;
 in vec3 fColor;
 
 out vec4 outColor;
 
 void main()
 {
-	outColor = vec4(fColor, 1.0);
+	/* XXX classic Blender hair normal == crap */
+	vec3 N = normalize(fTangent);
+
+	/* view vector computation, depends on orthographics or perspective */
+	vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(fPosition) : vec3(0.0, 0.0, -1.0);
+
+	vec3 L_diffuse = vec3(0.0);
+	vec3 L_specular = vec3(0.0);
+	for (int i = 0; i < NUM_LIGHTS; i++) {
+		/* todo: this is a slow check for disabled lights */
+		if (gl_LightSource[i].specular.a == 0.0)
+			continue;
+
+		float intensity = 1.0;
+		vec3 light_direction;
+
+		if (gl_LightSource[i].position.w == 0.0) {
+			/* directional light */
+			light_direction = gl_LightSource[i].position.xyz;
+		}
+		else {
+			/* point light */
+			vec3 d = gl_LightSource[i].position.xyz - fPosition;
+			light_direction = normalize(d);
+
+			/* spot light cone */
+			if (gl_LightSource[i].spotCutoff < 90.0) {
+				float cosine = max(dot(light_direction, -gl_LightSource[i].spotDirection), 0.0);
+				intensity = pow(cosine, gl_LightSource[i].spotExponent);
+				intensity *= step(gl_LightSource[i].spotCosCutoff, cosine);
+			}
+
+			/* falloff */
+			float distance = length(d);
+
+			intensity /= gl_LightSource[i].constantAttenuation +
+			             gl_LightSource[i].linearAttenuation * distance +
+			             gl_LightSource[i].quadraticAttenuation * distance * distance;
+		}
+
+		/* diffuse light */
+		vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
+		float diffuse_bsdf = max(dot(N, light_direction), 0.0);
+		L_diffuse += light_diffuse * diffuse_bsdf * intensity;
+
+		/* specular light */
+		vec3 light_specular = gl_LightSource[i].specular.rgb;
+		vec3 H = normalize(light_direction - V);
+
+		float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
+		L_specular += light_specular * specular_bsdf * intensity;
+	}
+
+	/* sum lighting */
+	
+	vec3 L = gl_FrontLightModelProduct.sceneColor.rgb;
+	//L += L_diffuse * gl_FrontMaterial.diffuse.rgb;
+	//L += L_specular * gl_FrontMaterial.specular.rgb;
+	//float alpha = gl_FrontMaterial.diffuse.a;
+	L += L_diffuse * fColor.rgb;
+	float alpha = 1.0;
+
+	/* write out fragment color */
+	outColor = vec4(L, alpha);
 }
diff --git a/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl b/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl
index a02760b..eb5b5a4 100644
--- a/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl
@@ -8,6 +8,8 @@ in vec3 vColor[];
 in uvec4 v_control_index[];
 in vec4 v_control_weight[];
 
+out vec3 fPosition;
+out vec3 fTangent;
 out vec3 fColor;
 
 uniform usamplerBuffer control_curves;
@@ -18,20 +20,20 @@ bool is_valid_index(uint index)
 	return index < uint(0xFFFFFFFF);
 }
 
-void emit_vertex(in vec4 loc)
+void emit_vertex(in vec3 location, in vec3 tangent)
 {
-	gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(loc.xyz, 1.0);
+	gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(location, 1.0);
+	fPosition = (gl_ModelViewMatrix * vec4(location, 1.0)).xyz;
+	fTangent = (gl_ModelViewMatrix * vec4(tangent, 0.0)).xyz;
+	fColor = vColor[0];
+	//fColor = vec3(float(i)/float(num_verts-1), 1.0-float(i)/float(num_verts-1), 0.0);
+	//fColor = vec3(float(t[0]), 0.0, 0.0);
 	EmitVertex();
 }
 
 void main()
 {
-	fColor = vColor[0];
-	
-	vec4 root = gl_in[0].gl_Position;
-	
-	emit_vertex(root);
-	
+	vec3 root = gl_in[0].gl_Position.xyz;
 	
 	int index[4] = int[4](int(v_control_index[0].x),
 	                      int(v_control_index[0].y),
@@ -49,8 +51,8 @@ void main()
 	int cvert_begin[4];
 	int num_cverts[4];
 	float fnum_verts = 0.0;
-	vec4 croot[4];
-	vec4 offset[4];
+	vec3 croot[4];
+	vec3 offset[4];
 	for (int k = 0; k < 4; ++k) {
 		uvec4 curve = texelFetch(control_curves, index[k]);
 		cvert_begin[k] = int(curve.x);
@@ -58,7 +60,7 @@ void main()
 		
 		fnum_verts += weight[k] * float(num_cverts[k]);
 		
-		croot[k] = texelFetch(control_points, cvert_begin[k]);
+		croot[k] = texelFetch(control_points, cvert_begin[k]).xyz;
 		offset[k] = root - croot[k];
 	}
 	int num_verts = max(int(ceil(fnum_verts)), 2);
@@ -68,12 +70,11 @@ void main()
 		dt[k] = float(num_cverts[k] - 1) / float(num_verts - 1);
 	}
 
-	//fColor = vec3(0.0, 1.0, 0.0);
-	emit_vertex(root);
-
+	vec3 loc = root;
+	vec3 tangent;
 	float t[4] = float[4](dt[0], dt[1], dt[2], dt[3]);
 	for (int i = 1; i < num_verts; ++i) {
-		vec4 loc = vec4(0.0, 0.0, 0.0, 1.0);
+		vec3 next_loc = vec3(0.0, 0.0, 0.0);
 
 		for (int k = 0; k < 4; ++k) {
 			if (!valid[k])
@@ -83,18 +84,20 @@ void main()
 			int ci1 = ci0 + 1;
 			float lambda = t[k] - floor(t[k]);
 			/* XXX could use texture filtering to do this for us? */
-			vec4 cloc0 = texelFetch(control_points, cvert_begin[k] + ci0);
-			vec4 cloc1 = texelFetch(control_points, cvert_begin[k] + ci1);
-			vec4 cloc = mix(cloc0, cloc1, lambda) + offset[k];
+			vec3 next_cloc0 = texelFetch(control_points, cvert_begin[k] + ci0).xyz;
+			vec3 next_cloc1 = texelFetch(control_points, cvert_begin[k] + ci1).xyz;
+			vec3 next_cloc = mix(next_cloc0, next_cloc1, lambda) + offset[k];
 			
-			loc += weight[k] * cloc;
+			next_loc += weight[k] * next_cloc;
 			t[k] += dt[k];
 		}
 
-		//fColor = vec3(float(i)/float(num_verts-1), 1.0-float(i)/float(num_verts-1), 0.0);
-		//fColor = vec3(float(t[0]), 0.0, 0.0);
-		emit_vertex(loc);
+		tangent = next_loc - loc;
+		emit_vertex(loc, tangent);
+		loc = next_loc;
 	}
+	/* last vertex */
+	emit_vertex(loc, tangent);
 	
 	EndPrimitive();
 }




More information about the Bf-blender-cvs mailing list