[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53520] branches/ge_harmony/source/blender : Cleaning up the shader merging code.

Daniel Stokes kupomail at gmail.com
Thu Jan 3 08:36:56 CET 2013


Revision: 53520
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53520
Author:   kupoman
Date:     2013-01-03 07:36:48 +0000 (Thu, 03 Jan 2013)
Log Message:
-----------
Cleaning up the shader merging code. Also, now global and custom shaders should run along side the generated shader. This allows the user to use the traditional material system, while rendering out some extra information to the other render targets (such as normals).

Modified Paths:
--------------
    branches/ge_harmony/source/blender/blenkernel/BKE_shader.h
    branches/ge_harmony/source/blender/blenkernel/intern/shader.c
    branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.c
    branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.h
    branches/ge_harmony/source/blender/gpu/intern/gpu_material.c

Modified: branches/ge_harmony/source/blender/blenkernel/BKE_shader.h
===================================================================
--- branches/ge_harmony/source/blender/blenkernel/BKE_shader.h	2013-01-03 07:01:41 UTC (rev 53519)
+++ branches/ge_harmony/source/blender/blenkernel/BKE_shader.h	2013-01-03 07:36:48 UTC (rev 53520)
@@ -43,7 +43,11 @@
 
 struct Shader *BKE_shader_add(const char *name);
 struct Shader *BKE_shader_copy(struct Shader *sh);
+struct Shader *BKE_shader_empty();
 
+void BKE_shader_source_merge(Shader *dst, const Shader *src);
+void BKE_shader_source_merge_ch(Shader *dst, const char *src);
+
 void BKE_shader_read_source(struct Shader *sh, struct Main *main);
 #ifdef __cplusplus
 }

Modified: branches/ge_harmony/source/blender/blenkernel/intern/shader.c
===================================================================
--- branches/ge_harmony/source/blender/blenkernel/intern/shader.c	2013-01-03 07:01:41 UTC (rev 53519)
+++ branches/ge_harmony/source/blender/blenkernel/intern/shader.c	2013-01-03 07:36:48 UTC (rev 53520)
@@ -43,11 +43,13 @@
 #include "BKE_text.h"
 
 #include "BLI_string.h"
+#include "BLI_dynstr.h"
 #include "BLI_fileops.h"
 #include "BLI_path_util.h"
 
 void init_shader(Shader *sh)
 {
+	sh->source = NULL;
 	sh->type = SHADER_TYPE_FRAGMENT;
 	sh->location = SHADER_LOC_BUILTIN;
 
@@ -56,6 +58,8 @@
 	sh->uniforms.first = NULL;
 	sh->uniforms.last = NULL;
 
+	sh->geom_in = sh->geom_out = -1;
+
 	sh->uniform_cache = BLI_ghash_str_new("Uniform Cache");
 }
 
@@ -83,6 +87,90 @@
 	return shn;
 }
 
+struct Shader *BKE_shader_empty()
+{
+	Shader *sh;
+	sh = MEM_mallocN(sizeof(Shader), "Empty Shader");
+	init_shader(sh);
+	return sh;
+}
+
+void BKE_shader_source_merge(Shader *dst, const Shader *src)
+{
+	DynStr *new_source = BLI_dynstr_new();
+	char fname1[40] = "main\0";
+	char fname2[40] = "main\0";
+	char count[33];
+	char i = 0;
+	char *dst_main, *src_main, *search;
+
+	/* Only one type of geometry i/o can be used */
+	dst->geom_in = src->geom_in;
+	dst->geom_out = src->geom_out;
+
+	/* Handle a couple of NULL cases */
+	if (src->source == NULL)
+		return;
+
+	if (dst->source == NULL) {
+		dst->source = MEM_mallocN(strlen(src->source)+1, "Merged shader source");
+		strcpy(dst->source, src->source);
+		return;
+	}
+
+	/* Find main, and assume there is nothing after it */
+	dst_main = strstr(dst->source, "void main");
+	src_main = strstr(src->source, "void main");
+
+	/* Put the fluff into the new shader */
+	BLI_dynstr_nappend(new_source, dst->source, dst_main-dst->source);
+	BLI_dynstr_nappend(new_source, src->source, src_main-src->source);
+
+	/* Find a new name for the first main */
+	search = BLI_dynstr_get_cstring(new_source);
+	do {
+		itoa(i++, count, 10);
+		strcpy(fname1, "main");
+		strcat(fname1, count);
+	}while (search = strstr(dst->source, fname1));
+	search = BLI_dynstr_get_cstring(new_source);
+
+	/* Add the first main back in with new name */
+	while (*(dst_main++) != '(');
+	BLI_dynstr_appendf(new_source, "void %s %s", fname1, --dst_main);
+
+	/* Find a name for the second main */
+	do {
+		itoa(i++, count, 10);
+		strcpy(fname2, "main");
+		strcat(fname2, count);
+	}while (search = strstr(dst->source, fname2));
+
+	/* Add the second main back in with new name */
+	while (*(src_main++) != '(');
+	BLI_dynstr_appendf(new_source, "void %s %s", fname2, --src_main);
+
+	/* Build a new main function */
+	BLI_dynstr_appendf(new_source, "\nvoid main()\n{\t%s();\n\t%s();\n}", fname1, fname2);
+
+	/* Copy the DynStr back to dst->source and clean up*/
+	search = BLI_dynstr_get_cstring(new_source);
+	dst->source = MEM_mallocN(strlen(search)+1, "Merged shader source");
+	strcpy(dst->source, search);
+	BLI_dynstr_free(new_source);
+}
+
+void gather_uniforms(Shader *sh);
+void BKE_shader_source_merge_ch(Shader *dst, const char *src)
+{
+	Shader *sh = BKE_shader_empty();
+	sh->source = MEM_mallocN(strlen(src)+1, "Shader merge temp");
+	strcpy(sh->source, src);
+	gather_uniforms(sh);
+	BKE_shader_source_merge(dst, sh);
+	BKE_shader_free(sh);
+}
+
 int starts_with(const char *str, const char *start)
 {
 	int len, result;

Modified: branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.c
===================================================================
--- branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.c	2013-01-03 07:01:41 UTC (rev 53519)
+++ branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.c	2013-01-03 07:36:48 UTC (rev 53520)
@@ -44,6 +44,8 @@
 #include "BLI_ghash.h"
 #include "BLI_heap.h"
 
+#include "BKE_shader.h"
+
 #include "GPU_material.h"
 #include "GPU_extensions.h"
 
@@ -575,7 +577,7 @@
 		BLI_dynstr_append(ds, ");\n");
 	}
 
-	BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
+	BLI_dynstr_append(ds, "\n\tgl_FragData[0] = ");
 	codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
 	BLI_dynstr_append(ds, ";\n");
 }
@@ -1347,10 +1349,12 @@
 	return shader;
 }
 
-GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name, char* vert, char* frag, char* geom, short geomin, short geomout)
+GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name, ListBase *custom_shaders)
 {
 	GPUShader *shader;
 	GPUPass *pass;
+	Shader *cs, *sh_vert, *sh_frag, *sh_geom;
+	LinkData *link;
 	char *vertexcode, *fragmentcode, *geometrycode, *libcode=NULL;
 
 	/*if (!FUNCTION_LIB) {
@@ -1364,26 +1368,30 @@
 	gpu_nodes_get_vertex_attributes(nodes, attribs);
 	gpu_nodes_get_builtin_flag(nodes, builtins);
 
-	/* generate code and compile with opengl */
-	if (frag && strcmp(frag, ""))
-		fragmentcode = frag;
-	else
-	{
-		fragmentcode = code_generate_fragment(nodes, outlink->output, name);
-		libcode = glsl_material_library;
+	/* generate built in shader code */
+	sh_vert = BKE_shader_empty();
+	sh_frag = BKE_shader_empty();
+	sh_geom = BKE_shader_empty();
+
+	BKE_shader_source_merge_ch(sh_vert, code_generate_vertex(nodes));
+	BKE_shader_source_merge_ch(sh_frag, code_generate_fragment(nodes, outlink->output, name));
+	libcode = glsl_material_library;
+
+	/* merge custom shaders */
+	for (link = custom_shaders->first; link; link = link->next) {
+		cs = (Shader*)link->data;
+		if (cs->type == SHADER_TYPE_VERTEX)
+			BKE_shader_source_merge(sh_vert, cs);
+		else if (cs->type == SHADER_TYPE_FRAGMENT)
+			BKE_shader_source_merge(sh_frag, cs);
+		else if (cs->type == SHADER_TYPE_GEOMETRY)
+			BKE_shader_source_merge(sh_geom, cs);
 	}
-	
-	if (vert && strcmp(vert, ""))
-		vertexcode = vert;
-	else
-		vertexcode = code_generate_vertex(nodes);
 
-	if (geom && strcmp(geom, ""))
-		geometrycode = geom;
-	else
-		geometrycode = NULL;
 
-	shader = GPU_shader_create(vertexcode, fragmentcode, geometrycode, libcode, geomin, geomout);
+	/* compile with opengl */
+	shader = GPU_shader_create(sh_vert->source, sh_frag->source, sh_geom->source, libcode,
+		sh_geom->geom_in, sh_geom->geom_out);
 
 
 	/* failed? */
@@ -1399,9 +1407,9 @@
 
 	pass->output = outlink->output;
 	pass->shader = shader;
-	pass->fragmentcode = fragmentcode;
-	pass->vertexcode = vertexcode;
-	pass->geometrycode = geometrycode;
+	pass->fragmentcode = sh_frag->source;
+	pass->vertexcode = sh_vert->source;
+	pass->geometrycode = sh_geom->source;
 	pass->libcode = glsl_material_library;
 
 	/* extract dynamic inputs and throw away nodes */

Modified: branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.h
===================================================================
--- branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.h	2013-01-03 07:01:41 UTC (rev 53519)
+++ branches/ge_harmony/source/blender/gpu/intern/gpu_codegen.h	2013-01-03 07:36:48 UTC (rev 53520)
@@ -172,7 +172,7 @@
 
 GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
 	struct GPUVertexAttribs *attribs, int *builtin, const char *name,
-		char* vert, char* frag, char* geom, short geomin, short geomout);
+		ListBase *custom_shaders);
 
 struct GPUShader *GPU_pass_shader(GPUPass *pass);
 

Modified: branches/ge_harmony/source/blender/gpu/intern/gpu_material.c
===================================================================
--- branches/ge_harmony/source/blender/gpu/intern/gpu_material.c	2013-01-03 07:01:41 UTC (rev 53519)
+++ branches/ge_harmony/source/blender/gpu/intern/gpu_material.c	2013-01-03 07:36:48 UTC (rev 53520)
@@ -216,78 +216,11 @@
 	if (material->outlink) {
 		GPUNodeLink *outlink;
 		GPUShader *shader;
-		CustomShader *cs;
-		DynStr *frag_vars = BLI_dynstr_new(), *frag_funcs = BLI_dynstr_new(), *frag_main = BLI_dynstr_new();
-		char *frag_funcs_c, *frag_main_c;
-		char *fname = "void functionx";
-		int fcount = 0;
-		char *frag=NULL, *vert=NULL, *geom=NULL;
-		int geom_in = SHADER_GEOM_IN_TRIS;
-		int geom_out = SHADER_GEOM_OUT_TRIANGLE_STRIP;
-		int source_len;
 
-		cs = (CustomShader*)material->ma->custom_shaders.first;
-		BLI_dynstr_append(frag_main, "\n\nvoid main()\n{\n");
-		while (cs) {
-			if (!cs->shader || !cs->shader->source) {
-				cs = cs->next;
-				continue;
-			}
-
-			if (cs->shader->type & SHADER_TYPE_VERTEX) {
-				if (vert) {
-					MEM_freeN(vert);
-				}
-				else {
-					vert = BLI_strdup(cs->shader->source);
-				}
-			}
-
-			else if (cs->shader->type & SHADER_TYPE_FRAGMENT) {
-				char *source = cs->shader->source;
-				char *split = strstr(source, "void main");
-				fname[13] = '0' + fcount++;
-				BLI_dynstr_nappend(frag_vars, source, split-source);
-				BLI_dynstr_append(frag_funcs, fname);
-				BLI_dynstr_append(frag_funcs, "()");
-				split = strstr(split, "{");
-				BLI_dynstr_append(frag_funcs, split);
-				BLI_dynstr_appendf(frag_main, "\t%s();\n", fname+5);
-			}
-
-			else if (cs->shader->type & SHADER_TYPE_GEOMETRY) {
-				if (geom) {
-					MEM_freeN(geom);
-				}
-				else {
-					geom = BLI_strdup(cs->shader->source);
-					geom_in = cs->shader->geom_in;
-					geom_out = cs->shader->geom_out;
-				}
-			}
-
-			cs = cs->next;
-		}
-
-		if (fcount > 0) {
-			BLI_dynstr_append(frag_main, "}\n");
-			frag_funcs_c = BLI_dynstr_get_cstring(frag_funcs);
-			frag_main_c = BLI_dynstr_get_cstring(frag_main);
-			BLI_dynstr_append(frag_vars, frag_funcs_c);
-			BLI_dynstr_append(frag_vars, frag_main_c);
-			MEM_freeN(frag_funcs_c);
-			MEM_freeN(frag_main_c);
-			frag = BLI_dynstr_get_cstring(frag_vars);
-		}
-		
-		BLI_dynstr_free(frag_vars);
-		BLI_dynstr_free(frag_funcs);
-		BLI_dynstr_free(frag_main);
-
 		outlink = material->outlink;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list