[Bf-blender-cvs] [abb976a] master: OpenSubdiv: Optimize drawing shader

Sergey Sharybin noreply at git.blender.org
Tue Aug 4 10:55:32 CEST 2015


Commit: abb976ae889985a973d322bd7f3a792495553ff3
Author: Sergey Sharybin
Date:   Tue Aug 4 10:49:32 2015 +0200
Branches: master
https://developer.blender.org/rBabb976ae889985a973d322bd7f3a792495553ff3

OpenSubdiv: Optimize drawing shader

The idea is to cut as much code as possible and use compile-time
ifdefs rather than runtime if() statements.

Gives about 2x speedup on catmark_car model from OpenSubdiv repository
making our FPS much closer to what glViewer is capable of.

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

M	intern/opensubdiv/gpu_shader_opensubd_display.glsl
M	intern/opensubdiv/opensubdiv_gpu_capi.cc

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

diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index 110898a..e343c95 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -215,8 +215,6 @@ uniform vec4 specular;
 uniform float shininess;
 
 uniform sampler2D texture_buffer;
-uniform bool use_color_material;
-uniform bool use_texture_2d;
 
 in block {
 	VertexData v;
@@ -236,99 +234,89 @@ void main()
 	vec3 L_diffuse = vec3(0.0);
 	vec3 L_specular = vec3(0.0);
 
-	if (use_color_material == false) {
-		/* Assume NUM_SOLID_LIGHTS directional lights. */
-		for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
-			vec3 light_direction = lightSource[i].position.xyz;
-
-			/* Diffuse light. */
-			vec3 light_diffuse = lightSource[i].diffuse.rgb;
-			float diffuse_bsdf = max(dot(N, light_direction), 0.0);
-			L_diffuse += light_diffuse * diffuse_bsdf;
-
-			/* Specular light. */
-			vec4 Plight = lightSource[i].position;
-			vec3 l = (Plight.w == 0.0)
-				? normalize(Plight.xyz) : normalize(Plight.xyz -
-				                                    inpt.v.position.xyz);
-			vec3 light_specular = lightSource[i].specular.rgb;
-			vec3 H = normalize(l + vec3(0,0,1));
-			float specular_bsdf = pow(max(dot(N, H), 0.0),
-			                          shininess);
-			L_specular += light_specular * specular_bsdf;
-		}
+#ifndef USE_COLOR_MATERIAL
+	/* Assume NUM_SOLID_LIGHTS directional lights. */
+	for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
+		vec4 Plight = lightSource[i].position;
+#ifdef USE_DIRECTIONAL_LIGHT
+		vec3 l = (Plight.w == 0.0)
+		            ? normalize(Plight.xyz)
+		            : normalize(inpt.v.position.xyz);
+#else  /* USE_DIRECTIONAL_LIGHT */
+		/* TODO(sergey): We can normalize it outside of the shader. */
+		vec3 l = normalize(Plight.xyz);
+#endif  /* USE_DIRECTIONAL_LIGHT */
+		vec3 h = normalize(l + vec3(0, 0, 1));
+		float d = max(0.0, dot(N, l));
+		float s = pow(max(0.0, dot(N, h)), 500.0f);
+		L_diffuse += d * lightSource[i].diffuse;
+		L_specular += s * lightSource[i].specular;
 	}
-	else {
-		vec3 varying_position = inpt.v.position.xyz;
-		vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
-			normalize(varying_position): vec3(0.0, 0.0, -1.0);
-		for (int i = 0; i < num_enabled_lights; i++) {
-			/* todo: this is a slow check for disabled lights */
-			if (lightSource[i].specular.a == 0.0)
-				continue;
-
-			float intensity = 1.0;
-			vec3 light_direction;
-
-			if (lightSource[i].position.w == 0.0) {
-				/* directional light */
-				light_direction = lightSource[i].position.xyz;
-			}
-			else {
-				/* point light */
-				vec3 d = lightSource[i].position.xyz - varying_position;
-				light_direction = normalize(d);
-
-				/* spot light cone */
-				if (lightSource[i].spotCutoff < 90.0) {
-					float cosine = max(dot(light_direction,
-					                       -lightSource[i].spotDirection.xyz),
-					                   0.0);
-					intensity = pow(cosine, lightSource[i].spotExponent);
-					intensity *= step(lightSource[i].spotCosCutoff, cosine);
-				}
-
-				/* falloff */
-				float distance = length(d);
-
-				intensity /= lightSource[i].constantAttenuation +
-					lightSource[i].linearAttenuation * distance +
-					lightSource[i].quadraticAttenuation * distance * distance;
+#else  /* USE_COLOR_MATERIAL */
+	vec3 varying_position = inpt.v.position.xyz;
+	vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
+		normalize(varying_position): vec3(0.0, 0.0, -1.0);
+	for (int i = 0; i < num_enabled_lights; i++) {
+		/* todo: this is a slow check for disabled lights */
+		if (lightSource[i].specular.a == 0.0)
+			continue;
+
+		float intensity = 1.0;
+		vec3 light_direction;
+
+		if (lightSource[i].position.w == 0.0) {
+			/* directional light */
+			light_direction = lightSource[i].position.xyz;
+		}
+		else {
+			/* point light */
+			vec3 d = lightSource[i].position.xyz - varying_position;
+			light_direction = normalize(d);
+
+			/* spot light cone */
+			if (lightSource[i].spotCutoff < 90.0) {
+				float cosine = max(dot(light_direction,
+				                       -lightSource[i].spotDirection.xyz),
+				                   0.0);
+				intensity = pow(cosine, lightSource[i].spotExponent);
+				intensity *= step(lightSource[i].spotCosCutoff, cosine);
 			}
 
-			/* diffuse light */
-			vec3 light_diffuse = lightSource[i].diffuse.rgb;
-			float diffuse_bsdf = max(dot(N, light_direction), 0.0);
-			L_diffuse += light_diffuse*diffuse_bsdf*intensity;
+			/* falloff */
+			float distance = length(d);
 
-			/* specular light */
-			vec3 light_specular = 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;
+			intensity /= lightSource[i].constantAttenuation +
+				lightSource[i].linearAttenuation * distance +
+				lightSource[i].quadraticAttenuation * distance * distance;
 		}
+
+		/* diffuse light */
+		vec3 light_diffuse = 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 = 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;
 	}
+#endif  /* USE_COLOR_MATERIAL */
 
 	/* Compute diffuse color. */
-	float alpha;
-	if (use_texture_2d) {
-		L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
-	}
-	else {
-		L_diffuse *= diffuse.rgb;
-	}
-	alpha = diffuse.a;
+#ifdef USE_TEXTURE_2D
+	L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
+#else
+	L_diffuse *= diffuse.rgb;
+#endif
 
 	/* Sum lighting. */
-	vec3 L = /*gl_FrontLightModelProduct.sceneColor.rgb +*/ L_diffuse;
-	if (shininess != 0.0f) {
-		L += L_specular * specular.rgb;
-	}
+	vec3 L = L_diffuse + L_specular * specular.rgb;
 
 	/* Write out fragment color. */
-	gl_FragColor = vec4(L, alpha);
+	gl_FragColor = vec4(L, diffuse.a);
 #endif
 }
 
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index d46211f..9498f93 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -86,8 +86,10 @@ typedef struct Transform {
 static bool g_use_osd_glsl = false;
 static int g_active_uv_index = -1;
 
-static GLuint g_flat_fill_program = 0;
-static GLuint g_smooth_fill_program = 0;
+static GLuint g_flat_fill_solid_program = 0;
+static GLuint g_flat_fill_texture2d_program = 0;
+static GLuint g_smooth_fill_solid_program = 0;
+static GLuint g_smooth_fill_texture2d_program = 0;
 static GLuint g_wireframe_program = 0;
 
 static GLuint g_lighting_ub = 0;
@@ -324,15 +326,8 @@ void bindProgram(PartitionedGLMeshInterface * /*mesh*/,
 	glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
 
 	/* Color */
-	GLboolean use_lighting, use_color_material, use_texture_2d;
+	GLboolean use_lighting;
 	glGetBooleanv(GL_LIGHTING, &use_lighting);
-	glGetBooleanv(GL_COLOR_MATERIAL, &use_color_material);
-	glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
-
-	glUniform1i(glGetUniformLocation(program, "use_color_material"),
-	            use_color_material);
-	glUniform1i(glGetUniformLocation(program, "use_texture_2d"),
-	            use_texture_2d);
 
 	if (use_lighting) {
 		float color[4];
@@ -376,8 +371,10 @@ void openSubdiv_osdGLDisplayInit(void)
 {
 	static bool need_init = true;
 	if (need_init) {
-		g_flat_fill_program = linkProgram("#define FLAT_SHADING\n");
-		g_smooth_fill_program = linkProgram("#define SMOOTH_SHADING\n");
+		g_flat_fill_solid_program = linkProgram("#define FLAT_SHADING\n");
+		g_flat_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
+		g_smooth_fill_solid_program = linkProgram("#define SMOOTH_SHADING\n");
+		g_smooth_fill_texture2d_program = linkProgram("#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
 		g_wireframe_program = linkProgram("#define WIREFRAME\n");
 
 		glGenBuffers(1, &g_lighting_ub);
@@ -394,11 +391,17 @@ void openSubdiv_osdGLDisplayDeinit(void)
 	if (g_lighting_ub != 0) {
 		glDeleteBuffers(1, &g_lighting_ub);
 	}
-	if (g_flat_fill_program) {
-		glDeleteProgram(g_flat_fill_program);
+	if (g_flat_fill_solid_program) {
+		glDeleteProgram(g_flat_fill_solid_program);
+	}
+	if (g_flat_fill_texture2d_program) {
+		glDeleteProgram(g_flat_fill_texture2d_program);
+	}
+	if (g_smooth_fill_solid_program) {
+		glDeleteProgram(g_flat_fill_solid_program);
 	}
-	if (g_smooth_fill_program) {
-		glDeleteProgram(g_flat_fill_program);
+	if (g_smooth_fill_texture2d_program) {
+		glDeleteProgram(g_smooth_fill_texture2d_program);
 	}
 	if (g_wireframe_program) {
 		glDeleteProgram(g_wireframe_program);
@@ -505,12 +508,26 @@ static GLuint preapre_patchDraw(PartitionedGLMeshInterface *mesh,
 		return program;
 	}
 
-	program = g_smooth_fill_program;
 	if (fill_quads) {
 		int model;
+		GLboolean use_texture_2d;
 		glGetIntegerv(GL_SHADE_MODEL, &model);
+		glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
 		if (model == GL_FLAT) {
-			program = g_flat_fill_program;
+			if (use_texture_2d) {
+				program = g_flat_fill_texture2d_program;
+			}
+			else {
+				program = g_flat_fill_solid_program;
+			}
+		}
+		else {
+			if (use_texture_2d) {
+				program = g_smooth_fill_texture2d_program;
+			}
+			else {
+				program = g_smooth_fill_solid_program;
+			}
 		}
 	}
 	else {




More information about the Bf-blender-cvs mailing list