Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntony Riakiotakis <kalast@gmail.com>2015-04-09 21:20:33 +0300
committerAntony Riakiotakis <kalast@gmail.com>2015-04-09 21:20:50 +0300
commit866532360c75298c88dc51724e878255295b98df (patch)
tree31974b583480531ab8c2bcd8baff75d1ea329ac0 /source/blender/gpu
parent7ea4163e1e5a33d38573371c8b19969b051d5ea2 (diff)
Fix T31546 fragment program gets created every frame
That was really crappy indeed. Now we have a separate API for low level OpenGL programs, plus a nice interface for GPU, also removes some GL calls from main code as a plus :) The source for the programs is also moved to nice external .glsl files (not sure which extension convention GPU assemply uses)
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt5
-rw-r--r--source/blender/gpu/GPU_extensions.h25
-rw-r--r--source/blender/gpu/SConscript2
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c115
-rw-r--r--source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl32
-rw-r--r--source/blender/gpu/shaders/gpu_program_smoke_frag.glsl27
6 files changed, 200 insertions, 6 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 97b0e7e1e0e..23a2b77d1e7 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -57,6 +57,9 @@ set(SRC
intern/gpu_compositing.c
intern/gpu_debug.c
+ shaders/gpu_program_smoke_frag.glsl
+ shaders/gpu_program_smoke_color_frag.glsl
+
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
shaders/gpu_shader_fx_dof_frag.glsl
@@ -89,6 +92,8 @@ set(SRC
intern/gpu_private.h
)
+data_to_c_simple(shaders/gpu_program_smoke_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_program_smoke_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index de0af815bf4..27a4396e5d8 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -52,6 +52,9 @@ typedef struct GPUOffScreen GPUOffScreen;
struct GPUShader;
typedef struct GPUShader GPUShader;
+struct GPUProgram;
+typedef struct GPUProgram GPUProgram;
+
/* GPU extensions support */
void GPU_extensions_disable(void);
@@ -181,6 +184,18 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
+/* Builtin/Non-generated shaders */
+typedef enum GPUProgramType {
+ GPU_PROGRAM_TYPE_FRAGMENT = 0
+} GPUProgramType;
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
+void GPU_program_free(GPUProgram *program);
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
+void GPU_program_bind(GPUProgram *);
+void GPU_program_unbind(GPUProgram *);
+
/* GPU Shader
* - only for fragment shaders now
* - must call texture bind before setting a texture as uniform! */
@@ -205,11 +220,17 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name);
/* Builtin/Non-generated shaders */
typedef enum GPUBuiltinShader {
- GPU_SHADER_VSM_STORE = (1<<0),
- GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1),
+ GPU_SHADER_VSM_STORE = 0,
+ GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
} GPUBuiltinShader;
+typedef enum GPUBuiltinProgram {
+ GPU_PROGRAM_SMOKE = 0,
+ GPU_PROGRAM_SMOKE_COLORED = 1,
+} GPUBuiltinProgram;
+
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
void GPU_shader_free_builtin_shaders(void);
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index 8d0ef394a06..ff5fb42c021 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -63,6 +63,8 @@ if env['WITH_BF_DDS']:
# generated data files
import os
sources.extend((
+ os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_color_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 363e19908e5..e8595ecc67c 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -77,6 +77,8 @@
*/
/* Non-generated shaders */
+extern char datatoc_gpu_program_smoke_frag_glsl[];
+extern char datatoc_gpu_program_smoke_color_frag_glsl[];
extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
@@ -94,6 +96,8 @@ extern char datatoc_gpu_shader_fx_lib_glsl[];
typedef struct GPUShaders {
GPUShader *vsm_store;
GPUShader *sep_gaussian_blur;
+ GPUProgram *smoke;
+ GPUProgram *smoke_colored;
/* cache for shader fx. Those can exist in combinations so store them here */
GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
} GPUShaders;
@@ -1430,7 +1434,13 @@ struct GPUShader {
int uniforms; /* required uniforms */
};
-static void shader_print_errors(const char *task, char *log, const char **code, int totcode)
+struct GPUProgram {
+ GPUProgramType type;
+ GLuint prog;
+};
+
+
+static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
{
int i;
int line = 1;
@@ -1504,6 +1514,70 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
return;
}
+void GPU_program_bind(GPUProgram *program)
+{
+ glEnable(program->type);
+ glBindProgramARB(program->type, program->prog);
+}
+
+void GPU_program_unbind(GPUProgram *program)
+{
+ glDisable(program->type);
+ glBindProgramARB(program->type, 0);
+}
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
+{
+ GPUProgram *program;
+ GLint error_pos, is_native;
+
+ if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
+ return NULL;
+
+ program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
+
+ switch (type) {
+ case GPU_PROGRAM_TYPE_FRAGMENT:
+ program->type = GL_FRAGMENT_PROGRAM_ARB;
+ break;
+ }
+
+ /* create the object and set its code string */
+ glGenProgramsARB(1, &program->prog);
+ glBindProgramARB(program->type, program->prog);
+
+ glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
+
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
+ if ((error_pos == -1) && (is_native == 1)) {
+ return program;
+ }
+ else {
+ /* glGetError is set before that, clear it */
+ while (glGetError() != GL_NO_ERROR)
+ ;
+ shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
+ MEM_freeN(program);
+ }
+
+ return NULL;
+}
+
+void GPU_program_free(GPUProgram *program)
+{
+ glDeleteProgramsARB(1, &program->prog);
+ MEM_freeN(program);
+}
+
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
+{
+ glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
+}
+
+
+
GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number)
{
GLint status;
@@ -1824,6 +1898,29 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
return retval;
}
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
+{
+ GPUProgram *retval = NULL;
+
+ switch (program) {
+ case GPU_PROGRAM_SMOKE:
+ if (!GG.shaders.smoke)
+ GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
+ retval = GG.shaders.smoke;
+ break;
+ case GPU_PROGRAM_SMOKE_COLORED:
+ if (!GG.shaders.smoke_colored)
+ GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
+ retval = GG.shaders.smoke_colored;
+ break;
+ }
+
+ if (retval == NULL)
+ printf("Unable to create a GPUProgram for builtin program: %d\n", program);
+
+ return retval;
+}
+
#define MAX_DEFINES 100
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
@@ -1905,18 +2002,28 @@ void GPU_shader_free_builtin_shaders(void)
int i;
if (GG.shaders.vsm_store) {
- MEM_freeN(GG.shaders.vsm_store);
+ GPU_shader_free(GG.shaders.vsm_store);
GG.shaders.vsm_store = NULL;
}
if (GG.shaders.sep_gaussian_blur) {
- MEM_freeN(GG.shaders.sep_gaussian_blur);
+ GPU_shader_free(GG.shaders.sep_gaussian_blur);
GG.shaders.sep_gaussian_blur = NULL;
}
+ if (GG.shaders.smoke) {
+ GPU_program_free(GG.shaders.smoke);
+ GG.shaders.smoke = NULL;
+ }
+
+ if (GG.shaders.smoke_colored) {
+ GPU_program_free(GG.shaders.smoke_colored);
+ GG.shaders.smoke_colored = NULL;
+ }
+
for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
if (GG.shaders.fx_shaders[i]) {
- MEM_freeN(GG.shaders.fx_shaders[i]);
+ GPU_shader_free(GG.shaders.fx_shaders[i]);
GG.shaders.fx_shaders[i] = NULL;
}
}
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
new file mode 100644
index 00000000000..a94c823f408
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
@@ -0,0 +1,32 @@
+!!ARBfp1.0
+PARAM dx = program.local[0];
+PARAM darkness = program.local[1];
+PARAM render = program.local[2];
+PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};
+TEMP temp, shadow, flame, spec, value;
+TEX temp, fragment.texcoord[0], texture[0], 3D;
+TEX shadow, fragment.texcoord[0], texture[1], 3D;
+TEX flame, fragment.texcoord[0], texture[2], 3D;
+TEX spec, flame.r, texture[3], 1D;
+# unpremultiply volume texture
+RCP value.r, temp.a;
+MUL temp.r, temp.r, value.r;
+MUL temp.g, temp.g, value.r;
+MUL temp.b, temp.b, value.r;
+# calculate shading factor from density
+MUL value.r, temp.a, darkness.a;
+MUL value.r, value.r, dx.r;
+MUL value.r, value.r, f.r;
+EX2 value.r, -value.r;
+# alpha
+SUB temp.a, 1.0, value.r;
+# shade colors
+MUL temp.r, temp.r, shadow.r;
+MUL temp.g, temp.g, shadow.r;
+MUL temp.b, temp.b, shadow.r;
+MUL temp.r, temp.r, value.r;
+MUL temp.g, temp.g, value.r;
+MUL temp.b, temp.b, value.r;
+# for now this just replace smoke shading if rendering fire
+CMP result.color, render.r, temp, spec;
+END
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
new file mode 100644
index 00000000000..04b171d24bd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
@@ -0,0 +1,27 @@
+!!ARBfp1.0
+PARAM dx = program.local[0];
+PARAM darkness = program.local[1];
+PARAM render = program.local[2];
+PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};
+TEMP temp, shadow, flame, spec, value;
+TEX temp, fragment.texcoord[0], texture[0], 3D;
+TEX shadow, fragment.texcoord[0], texture[1], 3D;
+TEX flame, fragment.texcoord[0], texture[2], 3D;
+TEX spec, flame.r, texture[3], 1D;
+# calculate shading factor from density
+MUL value.r, temp.a, darkness.a;
+MUL value.r, value.r, dx.r;
+MUL value.r, value.r, f.r;
+EX2 temp, -value.r;
+# alpha
+SUB temp.a, 1.0, temp.r;
+# shade colors
+MUL temp.r, temp.r, shadow.r;
+MUL temp.g, temp.g, shadow.r;
+MUL temp.b, temp.b, shadow.r;
+MUL temp.r, temp.r, darkness.r;
+MUL temp.g, temp.g, darkness.g;
+MUL temp.b, temp.b, darkness.b;
+# for now this just replace smoke shading if rendering fire
+CMP result.color, render.r, temp, spec;
+END