[Bf-blender-cvs] [dfe2743] opensubdiv-modifier: OpenSubdiv: Update GLSL code to use geometry shader

Sergey Sharybin noreply at git.blender.org
Wed Jul 16 19:01:58 CEST 2014


Commit: dfe2743ca07c924ab09c98cc9941a972f5344264
Author: Sergey Sharybin
Date:   Wed Jul 16 21:04:58 2014 +0600
https://developer.blender.org/rBdfe2743ca07c924ab09c98cc9941a972f5344264

OpenSubdiv: Update GLSL code to use geometry shader

This bumps GLSL requirement for the GPU, but this is the only way
we can support fare-vertex attributes. Shader currently supports
solid draw only but it've got lighting model hooked up.

This gives quite noticeable slowdown on my gt620, but this card
is not really something powerful and likely code could be improved
later.

This also allowed to have proper normals for flat shading.

For now the code stays disabled for until some runtime check or
so is implemented.

TODO: There are some matrix functions which are currently simply
copy-pasted from the blenlib, would be nice to clean this up.

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

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 cc5fb03..1c9d6b0 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -25,59 +25,145 @@
 
 /* ***** Vertex shader ***** */
 
-#version 130
+#version 150
+#extension GL_EXT_geometry_shader4 : enable
+
+struct VertexData {
+	vec4 position;
+	vec3 normal;
+};
 
 #ifdef VERTEX_SHADER
 
 in vec3 normal;
 in vec3 position;
 
-out vec3 varying_normal;
-out vec3 varying_position;
+uniform mat4 modelViewMatrix;
+uniform mat3 normalMatrix;
+
+out block {
+	VertexData v;
+} outpt;
 
 void main()
 {
-	vec4 co = gl_ModelViewMatrix * vec4(position, 1.0);
+	outpt.v.position = modelViewMatrix * vec4(position, 1.0);
+	outpt.v.normal = normalize(normalMatrix * normal);
+}
 
-	varying_normal = normalize(gl_NormalMatrix * normal);
-	varying_position = co.xyz;
+#endif  /* VERTEX_SHADER */
 
-	gl_Position = gl_ProjectionMatrix * co;
+/* ***** geometry shader ***** */
+#ifdef GEOMETRY_SHADER
 
-#ifdef GPU_NVIDIA
-	/* Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA
-	 * graphic cards, while on ATI it can cause a software fallback.
-	 */
-	gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+layout(lines_adjacency) in;
+#ifndef WIREFRAME
+layout(triangle_strip, max_vertices = 4) out;
+#else
+layout(line_strip, max_vertices = 8) out;
 #endif
 
-#ifdef WIREFRAME
-	gl_FrontColor = gl_Color;
+uniform mat4 modelViewMatrix;
+uniform mat4 projectionMatrix;
+
+in block {
+	VertexData v;
+} inpt[4];
+
+out vec3 varying_position;
+out vec3 varying_normal;
+
+#ifdef FLAT_SHADING
+void emit(int index, vec3 normal)
+{
+	varying_position = inpt[index].v.position.xyz;
+	varying_normal = normal;
+	gl_Position = projectionMatrix * inpt[index].v.position;
+	EmitVertex();
+}
+#else
+void emit(int index)
+{
+	varying_position = inpt[index].v.position.xyz;
+	varying_normal = inpt[index].v.normal;
+	gl_Position = projectionMatrix * inpt[index].v.position;
+	EmitVertex();
+}
+#endif
+
+void main()
+{
+#ifdef FLAT_SHADING
+	vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
+	vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
+	vec3 n0 = normalize(cross(B, A));
+#  ifndef WIREFRAME
+	emit(0, n0);
+	emit(1, n0);
+	emit(3, n0);
+	emit(2, n0);
+#  else
+	emit(0, n0);
+	emit(1, n0);
+	emit(1, n0);
+	emit(2, n0);
+	emit(2, n0);
+	emit(3, n0);
+	emit(3, n0);
+	emit(0, n0);
+#  endif
+#else
+#  ifndef WIREFRAME
+	emit(0);
+	emit(1);
+	emit(3);
+	emit(2);
+#  else
+	emit(0);
+	emit(1);
+	emit(1);
+	emit(2);
+	emit(2);
+	emit(3);
+	emit(3);
+	emit(0);
+#  endif
 #endif
+
+	EndPrimitive();
 }
 
-#endif  /* VERTEX_SHADER */
+#endif  /* GEOMETRY_SHADER */
 
 /* ***** Fragment shader ***** */
 #ifdef FRAGMENT_SHADER
 
 #define NUM_SOLID_LIGHTS 3
 
-in vec3 varying_normal;
+struct LightSource {
+	vec4 position;
+	vec4 ambient;
+	vec4 diffuse;
+	vec4 specular;
+};
+
+uniform Lighting {
+	LightSource lightSource[NUM_SOLID_LIGHTS];
+};
+
+uniform vec4 diffuse;
+uniform vec4 specular;
+uniform float shininess;
+
 in vec3 varying_position;
+in vec3 varying_normal;
 
 void main()
 {
 #ifdef WIREFRAME
-	gl_FragColor = gl_Color;
+	gl_FragColor = diffuse;
 #else
-	/* Compute normal. */
-#ifdef SMOOTH_SHADING
 	vec3 N = varying_normal;
-#else
-	vec3 N = normalize(cross(dFdx(varying_position),
-	                         dFdy(varying_position)));
-#endif
 
 	if (!gl_FrontFacing)
 		N = -N;
@@ -88,30 +174,34 @@ void main()
 
 	/* Assume NUM_SOLID_LIGHTS directional lights. */
 	for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
-		vec3 light_direction = gl_LightSource[i].position.xyz;
+		vec3 light_direction = lightSource[i].position.xyz;
 
 		/* Diffuse light. */
-		vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
+		vec3 light_diffuse = lightSource[i].diffuse.rgb;
 		float diffuse_bsdf = max(dot(N, light_direction), 0.0);
-		L_diffuse += light_diffuse*diffuse_bsdf;
+		L_diffuse += light_diffuse * diffuse_bsdf;
+
+		vec4 Plight = lightSource[i].position;
+		vec3 l = (Plight.w == 0.0)
+			? normalize(Plight.xyz) : normalize(Plight.xyz - varying_position);
 
 		/* Specular light. */
-		vec3 light_specular = gl_LightSource[i].specular.rgb;
-		vec3 H = gl_LightSource[i].halfVector.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),
-		                          gl_FrontMaterial.shininess);
-		L_specular += light_specular*specular_bsdf;
+		                          shininess);
+		L_specular += light_specular * specular_bsdf;
 	}
 
 	/* Compute diffuse color. */
 	float alpha;
-	L_diffuse *= gl_FrontMaterial.diffuse.rgb;
-	alpha = gl_FrontMaterial.diffuse.a;
+	L_diffuse *= diffuse.rgb;
+	alpha = diffuse.a;
 
 	/* Sum lighting. */
-	vec3 L = gl_FrontLightModelProduct.sceneColor.rgb + L_diffuse;
-	L += L_specular*gl_FrontMaterial.specular.rgb;
+	vec3 L = /*gl_FrontLightModelProduct.sceneColor.rgb +*/ L_diffuse;
+	L += L_specular * specular.rgb;
 
 	/* Write out fragment color. */
 	gl_FragColor = vec4(L, alpha);
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index ce2c932..39f57dc 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -54,9 +54,119 @@ using OpenSubdiv::OsdGLMeshInterface;
 extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
 
 #ifndef OPENSUBDIV_LEGACY_DRAW
-static GLuint compileShader(GLenum shaderType,
-                            const char *section,
-                            const char *define)
+
+#define NUM_SOLID_LIGHTS 3
+typedef struct Light {
+	float position[4];
+	float ambient[4];
+	float diffuse[4];
+	float specular[4];
+} Light;
+
+typedef struct Lighting {
+	Light lights[NUM_SOLID_LIGHTS];
+} Lighting;
+
+/* TODO(sergey): This is actually duplicated code from BLI. */
+namespace {
+void copy_m3_m3(float m1[3][3], float m2[3][3])
+{
+	/* destination comes first: */
+	memcpy(&m1[0], &m2[0], 9 * sizeof(float));
+}
+
+void copy_m3_m4(float m1[3][3], float m2[4][4])
+{
+	m1[0][0] = m2[0][0];
+	m1[0][1] = m2[0][1];
+	m1[0][2] = m2[0][2];
+
+	m1[1][0] = m2[1][0];
+	m1[1][1] = m2[1][1];
+	m1[1][2] = m2[1][2];
+
+	m1[2][0] = m2[2][0];
+	m1[2][1] = m2[2][1];
+	m1[2][2] = m2[2][2];
+}
+
+void adjoint_m3_m3(float m1[3][3], float m[3][3])
+{
+	m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
+	m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
+	m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
+
+	m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
+	m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
+	m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
+
+	m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
+	m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
+	m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
+}
+
+float determinant_m3_array(float m[3][3])
+{
+	return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
+	        m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
+	        m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
+}
+
+bool invert_m3_m3(float m1[3][3], float m2[3][3])
+{
+	float det;
+	int a, b;
+	bool success;
+
+	/* calc adjoint */
+	adjoint_m3_m3(m1, m2);
+
+	/* then determinant old matrix! */
+	det = determinant_m3_array(m2);
+
+	success = (det != 0.0f);
+
+	if (det != 0.0f) {
+		det = 1.0f / det;
+		for (a = 0; a < 3; a++) {
+			for (b = 0; b < 3; b++) {
+				m1[a][b] *= det;
+			}
+		}
+	}
+
+	return success;
+}
+
+bool invert_m3(float m[3][3])
+{
+	float tmp[3][3];
+	bool success;
+
+	success = invert_m3_m3(tmp, m);
+	copy_m3_m3(m, tmp);
+
+	return success;
+}
+
+void transpose_m3(float mat[3][3])
+{
+	float t;
+
+	t = mat[0][1];
+	mat[0][1] = mat[1][0];
+	mat[1][0] = t;
+	t = mat[0][2];
+	mat[0][2] = mat[2][0];
+	mat[2][0] = t;
+	t = mat[1][2];
+	mat[1][2] = mat[2][1];
+	mat[2][1] = t;
+}
+
+GLuint compileShader(GLenum shaderType,
+                     const char *section,
+                     const char *define)
 {
 	const char *sources[3];
 	char sdefine[64];
@@ -85,11 +195,14 @@ static GLuint compileShader(GLenum shaderType,
 	return shader;
 }
 
-static GLuint linkProgram(const char *define)
+GLuint linkProgram(const char *define)
 {
 	GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
 	                                    "VERTEX_SHADER",
 	                                    define);
+	GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
+	                                      "GEOMETRY_SHADER",
+	                                      define);
 	GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
 	                                      "FRAGMENT_SHADER",
 	                                      define);
@@ -97,6 +210,7 @@ static GLuint linkProgram(const char *define)
 	GLuint program = glCreateProgram();
 
 	glAttachShader(program, vertexShader);
+	glAttachShader(program, geometryShader);
 	glAttachShader(program, fragmentShader);
 
 	glBindAttribLocation(program, 0, "position");
@@ -105,6 +219,7 @@ static GLuint linkProgram(const char *define)
 	glLinkProgram(program);
 
 	glDeleteShader(vertexShader);
+	glDeleteShader(geometryShader);
 	glDeleteShader(fragmentShader);
 
 	GLint status;
@@ -117,8 +232,87 @@ static GLuint linkProgram(const char *define)
 		exit(1);
 	}
 
+	GLuint uboIndex = glGetUniformBlockIndex(program, "Lighting");
+	if (uboIndex != GL_INVALID_INDEX)
+		glUniformBlockBinding(program, uboIndex, 0);
+
 	return program;
 }
+
+void bindProgram(int program,
+                 GLuint lighting_ub,
+                 Lighting *lightingData)
+{
+	glUseProgram(program);
+
+	/* Matricies */
+	float projection_matrix[16], model_view_matrix[16], normal_matrix[9];
+	glGetFloatv(GL_PROJECTION_MATRIX, projection_matrix);
+	glGetFloatv(GL_MODELVIEW_MATRIX, model_view_matrix);
+
+	glUniformMatrix4fv(glGetUniformLocation(program, "modelViewMatrix"),
+	                   1, false,
+	                   model_view_matrix);
+
+	glUniformMatrix4fv(glGetUniformLocation(program, "projectionMatrix"),
+	                   1, false,
+	                   projection_matrix);
+
+	copy_m3_m4((float (*)[3])normal_matrix, (float (*)[4])model_view_mat

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list