diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 67abab47ecb0..29d57e1b208c 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -491,6 +491,15 @@ def draw(self, context): col.row().prop(gs, "frame_type", expand=True) col.prop(gs, "frame_color", text="") +class RENDER_PT_game_color_management(RenderButtonsPanel, Panel): + bl_label = "Color Management" + COMPAT_ENGINES = {'BLENDER_GAME'} + + def draw(self, context): + layout = self.layout + gs = context.scene.game_settings + + layout.prop(gs, "color_management") class RENDER_PT_game_debug(RenderButtonsPanel, Panel): bl_label = "Debug" @@ -1052,6 +1061,7 @@ def draw(self, context): RENDER_PT_game_system, RENDER_PT_game_animations, RENDER_PT_game_display, + RENDER_PT_game_color_management, RENDER_PT_game_debug, SCENE_PT_game_physics, SCENE_PT_game_physics_obstacles, diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index 88420f4752e9..dd21ca8f1f69 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -257,7 +257,7 @@ def draw(self, context): class SCENE_PT_color_management(SceneButtonsPanel, Panel): bl_label = "Color Management" bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + COMPAT_ENGINES = {'BLENDER_RENDER'} def draw(self, context): layout = self.layout diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d48cf1909c6c..f6ef2877f5d7 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2333,6 +2333,12 @@ void BKE_scene_disable_color_management(Scene *scene) bool BKE_scene_check_color_management_enabled(const Scene *scene) { +#ifdef WITH_GAMEENGINE + if (BKE_scene_uses_blender_game(scene)) { + return (scene->gm.colorManagement == GAME_COLOR_MANAGEMENT_SRGB); + } +#endif + return !STREQ(scene->display_settings.display_device, "None"); } diff --git a/source/blender/blenloader/intern/versioning_upbge.c b/source/blender/blenloader/intern/versioning_upbge.c index 8fa1af0eca21..49a0a0f40a3f 100644 --- a/source/blender/blenloader/intern/versioning_upbge.c +++ b/source/blender/blenloader/intern/versioning_upbge.c @@ -309,5 +309,11 @@ void blo_do_versions_upbge(FileData *fd, Library *lib, Main *main) } } } + + if (!DNA_struct_elem_find(fd->filesdna, "GameData", "short", "colorManagement")) { + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + scene->gm.colorManagement = GAME_COLOR_MANAGEMENT_SRGB; + } + } } } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index caa4d2c0136f..29f81751ebe8 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3104,7 +3104,7 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { if (scene->world && (v3d->flag2 & V3D_SHOW_WORLD)) { RegionView3D *rv3d = ar->regiondata; - GPUMaterial *gpumat = GPU_material_world(scene, scene->world); + GPUMaterial *gpumat = GPU_material_world(scene, scene->world, 0); /* calculate full shader for background */ GPU_material_bind(gpumat, 1, 1.0, true, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index d5595baade11..d0793dea5480 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -132,6 +132,12 @@ typedef enum GPUBlendMode { GPU_BLEND_ALPHA_TO_COVERAGE = 16 } GPUBlendMode; +typedef enum GPUMaterialFlag { + GPU_MATERIAL_OPENSUBDIV = (1 << 0), + GPU_MATERIAL_INSTANCING = (1 << 1), + GPU_MATERIAL_NO_COLOR_MANAGEMENT = (1 << 2) +} GPUMaterialFlag; + typedef struct GPUNodeStack { GPUType type; const char *name; @@ -262,10 +268,10 @@ GPUBuiltin GPU_get_material_builtins(GPUMaterial *material); GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, const float obcol[4]); /* High level functions to create and use GPU materials */ -GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo); +GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo, GPUMaterialFlag flags); -GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv, bool is_instancing); -GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv); +GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, GPUMaterialFlag flags); +GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, GPUMaterialFlag flags); void GPU_material_free(struct ListBase *gpumaterial); void GPU_materials_free(struct Main *bmain); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 8f56c6fc8a40..0df5d9fffb56 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -112,12 +112,15 @@ typedef enum GPUBuiltinShader { GPU_SHADER_BLACK = 6, GPU_SHADER_BLACK_INSTANCING = 7, GPU_SHADER_DRAW_FRAME_BUFFER = 8, - GPU_SHADER_STEREO_STIPPLE = 9, - GPU_SHADER_STEREO_ANAGLYPH = 10, - GPU_SHADER_FRUSTUM_LINE = 11, - GPU_SHADER_FRUSTUM_SOLID = 12, - GPU_SHADER_FLAT_COLOR = 13, - GPU_SHADER_2D_BOX = 14, + GPU_SHADER_DRAW_FRAME_BUFFER_SRGB = 9, + GPU_SHADER_STEREO_STIPPLE = 10, + GPU_SHADER_STEREO_STIPPLE_SRGB = 11, + GPU_SHADER_STEREO_ANAGLYPH = 12, + GPU_SHADER_STEREO_ANAGLYPH_SRGB = 13, + GPU_SHADER_FRUSTUM_LINE = 14, + GPU_SHADER_FRUSTUM_SOLID = 15, + GPU_SHADER_FLAT_COLOR = 16, + GPU_SHADER_2D_BOX = 17, } GPUBuiltinShader; GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 726326e9d331..dfd382c3fc88 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1687,7 +1687,7 @@ void GPU_begin_object_materials( /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */ if (use_matcap) { GMS.gmatbuf[0] = v3d->defmaterial; - GPU_material_matcap(scene, v3d->defmaterial, use_opensubdiv); + GPU_material_matcap(scene, v3d->defmaterial, use_opensubdiv ? GPU_MATERIAL_OPENSUBDIV : 0); /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); @@ -1705,7 +1705,7 @@ void GPU_begin_object_materials( if (glsl) { GMS.gmatbuf[0] = &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv, false); + GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv ? GPU_MATERIAL_OPENSUBDIV : 0); } GMS.alphablend[0] = GPU_BLEND_SOLID; @@ -1719,7 +1719,7 @@ void GPU_begin_object_materials( if (ma == NULL) ma = &defmaterial; /* create glsl material if requested */ - gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv, false) : NULL; + gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv ? GPU_MATERIAL_OPENSUBDIV : 0) : NULL; if (gpumat) { /* do glsl only if creating it succeed, else fallback */ @@ -1835,7 +1835,7 @@ int GPU_object_material_bind(int nr, void *attribs) /* unbind glsl material */ if (GMS.gboundmat) { if (GMS.is_alpha_pass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, false)); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv ? GPU_MATERIAL_OPENSUBDIV : 0)); GMS.gboundmat = NULL; } @@ -1863,7 +1863,7 @@ int GPU_object_material_bind(int nr, void *attribs) float auto_bump_scale; - GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv, false); + GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv ? GPU_MATERIAL_OPENSUBDIV : 0); GPU_material_vertex_attributes(gpumat, gattribs); if (GMS.dob) { @@ -1968,7 +1968,7 @@ void GPU_object_material_unbind(void) glDisable(GL_CULL_FACE); if (GMS.is_alpha_pass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, false)); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv ? GPU_MATERIAL_OPENSUBDIV : 0)); GMS.gboundmat = NULL; } else diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index b250211b8aa3..19ae052a42e3 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -610,11 +610,11 @@ GPURenderBuffer *GPU_renderbuffer_create(int width, int height, int samples, GPU rb->depth = true; } else { - GLenum internalformat = GL_RGBA8; + GLenum internalformat = GL_RGBA12; switch (hdrtype) { case GPU_HDR_NONE: { - internalformat = GL_RGBA8; + internalformat = GL_RGBA12; break; } /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index c7491a74d545..e546e3b1ab42 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -133,12 +133,10 @@ struct GPUMaterial { int ininstmatloc; int ininstcolloc; - bool use_instancing; - ListBase lamps; bool bound; - bool is_opensubdiv; + GPUMaterialFlag flags; float har; }; @@ -249,8 +247,8 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam material->pass = GPU_generate_pass(&material->nodes, outlink, &material->attribs, &material->builtins, material->type, passname, - material->is_opensubdiv, - material->use_instancing, + material->flags & GPU_MATERIAL_OPENSUBDIV, + material->flags & GPU_MATERIAL_INSTANCING, GPU_material_use_new_shading_nodes(material)); if (!material->pass) @@ -288,7 +286,7 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY)); if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY)); - if (material->use_instancing) { + if (GPU_material_use_instancing(material)) { material->ininstposloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_POSITION_ATTRIB)); material->ininstmatloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_MATRIX_ATTRIB)); material->ininstcolloc = GPU_shader_get_attribute(shader, GPU_builtin_name(GPU_INSTANCING_COLOR_ATTRIB)); @@ -353,7 +351,7 @@ bool GPU_lamp_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma) bool GPU_material_use_instancing(GPUMaterial *material) { - return material->use_instancing; + return material->flags & GPU_MATERIAL_INSTANCING; } void GPU_material_bind_instancing_attrib(GPUMaterial *material, void *matrixoffset, void *positionoffset, void *coloroffset, unsigned int stride) @@ -612,10 +610,7 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node) bool GPU_material_do_color_management(GPUMaterial *mat) { - if (!BKE_scene_check_color_management_enabled(mat->scene)) - return false; - - return true; + return BKE_scene_check_color_management_enabled(mat->scene); } bool GPU_material_use_new_shading_nodes(GPUMaterial *mat) @@ -1332,13 +1327,14 @@ static void do_material_tex(GPUShadeInput *shi) GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude; int iFirstTimeNMap = 1; bool found_deriv_map = false; + const bool instancing = GPU_material_use_instancing(mat); GPU_link(mat, "set_value", GPU_uniform(&one), &stencil); GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm); GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco); GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - GPU_builtin((mat->use_instancing) ? GPU_INSTANCING_INVERSE_MATRIX : GPU_INVERSE_OBJECT_MATRIX), + GPU_builtin(instancing ? GPU_INSTANCING_INVERSE_MATRIX : GPU_INVERSE_OBJECT_MATRIX), GPU_builtin(GPU_VIEW_POSITION), &texco_object); #if 0 GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); @@ -1708,8 +1704,8 @@ static void do_material_tex(GPUShadeInput *shi) surf_pos, vNorg, GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - GPU_builtin((mat->use_instancing) ? GPU_INSTANCING_MATRIX : GPU_OBJECT_MATRIX), - GPU_builtin((mat->use_instancing) ? GPU_INSTANCING_INVERSE_MATRIX : GPU_INVERSE_OBJECT_MATRIX), + GPU_builtin(instancing ? GPU_INSTANCING_MATRIX : GPU_OBJECT_MATRIX), + GPU_builtin(instancing ? GPU_INSTANCING_INVERSE_MATRIX : GPU_INVERSE_OBJECT_MATRIX), fPrevMagnitude, vNacc, &fPrevMagnitude, &vNacc, &vR1, &vR2, &fDet); @@ -1946,6 +1942,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) GPUNodeLink *emit, *mistfac; Material *ma = shi->mat; World *world = mat->scene->world; + const bool instancing = GPU_material_use_instancing(mat); mat->dynproperty |= DYN_LAMP_CO; memset(shr, 0, sizeof(*shr)); @@ -2074,7 +2071,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) if (ma->shade_flag & MA_OBCOLOR) { GPU_link(mat, "shade_obcolor", shr->combined, - GPU_builtin((mat->use_instancing) ? GPU_INSTANCING_COLOR : GPU_OBCOLOR), &shr->combined); + GPU_builtin(instancing ? GPU_INSTANCING_COLOR : GPU_OBCOLOR), &shr->combined); } if (!(ma->mode & MA_NOMIST)) { @@ -2100,7 +2097,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) if (ma->shade_flag & MA_OBCOLOR) { mat->obcolalpha = 1; GPU_link(mat, "shade_alpha_obcolor", shr->combined, - GPU_builtin((mat->use_instancing) ? GPU_INSTANCING_COLOR : GPU_OBCOLOR), &shr->combined); + GPU_builtin(instancing ? GPU_INSTANCING_COLOR : GPU_OBCOLOR), &shr->combined); } } @@ -2141,7 +2138,7 @@ static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma) } /* new solid draw mode with glsl matcaps */ -GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv) +GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, GPUMaterialFlag flags) { GPUMaterial *mat; GPUNodeLink *outlink; @@ -2150,7 +2147,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv for (link = ma->gpumaterial.first; link; link = link->next) { GPUMaterial *current_material = (GPUMaterial *)link->data; if (current_material->scene == scene && - current_material->is_opensubdiv == use_opensubdiv) + current_material->flags == flags) { return current_material; } @@ -2160,7 +2157,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv mat = GPU_material_construct_begin(ma); mat->scene = scene; mat->type = GPU_MATERIAL_TYPE_MESH; - mat->is_opensubdiv = use_opensubdiv; + mat->flags = flags; if (ma->preview && ma->preview->rect[0]) { outlink = gpu_material_preview_matcap(mat, ma); @@ -2377,19 +2374,25 @@ static void gpu_material_old_world(struct GPUMaterial *mat, struct World *wo) GPU_material_output_link(mat, shr.combined); } -GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) +GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo, GPUMaterialFlag flags) { LinkData *link; GPUMaterial *mat; - for (link = wo->gpumaterial.first; link; link = link->next) - if (((GPUMaterial *)link->data)->scene == scene) + for (link = wo->gpumaterial.first; link; link = link->next) { + GPUMaterial *current_material = (GPUMaterial *)link->data; + if (current_material->scene == scene && + current_material->flags == flags) + { return link->data; + } + } /* allocate material */ mat = GPU_material_construct_begin(NULL); mat->scene = scene; mat->type = GPU_MATERIAL_TYPE_WORLD; + mat->flags = flags; /* create nodes */ if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) { @@ -2399,7 +2402,7 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) gpu_material_old_world(mat, wo); } - if (GPU_material_do_color_management(mat)) + if (GPU_material_do_color_management(mat) && !(mat->flags & GPU_MATERIAL_NO_COLOR_MANAGEMENT)) if (mat->outlink) GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); @@ -2417,14 +2420,14 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) } -GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv, bool is_instancing) +GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, GPUMaterialFlag flags) { GPUMaterial *mat; GPUNodeLink *outlink; LinkData *link; ListBase *gpumaterials; - if (is_instancing) { + if (flags & GPU_MATERIAL_INSTANCING) { gpumaterials = &ma->gpumaterialinstancing; } else { @@ -2434,7 +2437,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open for (link = gpumaterials->first; link; link = link->next) { GPUMaterial *current_material = (GPUMaterial *)link->data; if (current_material->scene == scene && - current_material->is_opensubdiv == use_opensubdiv) + current_material->flags == flags) { return current_material; } @@ -2444,8 +2447,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open mat = GPU_material_construct_begin(ma); mat->scene = scene; mat->type = GPU_MATERIAL_TYPE_MESH; - mat->use_instancing = is_instancing; - mat->is_opensubdiv = use_opensubdiv; + mat->flags = flags; mat->har = ma->har; /* render pipeline option */ @@ -2475,7 +2477,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open GPU_material_output_link(mat, outlink); } - if (GPU_material_do_color_management(mat) && !(ma->sss_flag)) + if (GPU_material_do_color_management(mat) && !(ma->sss_flag) && !(mat->flags & GPU_MATERIAL_NO_COLOR_MANAGEMENT)) if (mat->outlink) GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); @@ -3034,7 +3036,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) int liblen, fraglen; /* TODO(sergey): How to determine whether we need OSD or not here? */ - GPUMaterial *mat = GPU_material_from_blender(scene, ma, false, false); + GPUMaterial *mat = GPU_material_from_blender(scene, ma, 0); GPUPass *pass = (mat) ? mat->pass : NULL; if (pass && pass->fragmentcode && pass->vertexcode) { diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index e63eb4e1bcc7..482ac49a911e 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -87,9 +87,9 @@ static struct GPUShadersGlobal { GPUShader *smoke_coba; GPUShader *black; GPUShader *black_instancing; - GPUShader *draw_frame_buffer; - GPUShader *stereo_stipple; - GPUShader *stereo_anaglyph; + GPUShader *draw_frame_buffer[2]; + GPUShader *stereo_stipple[2]; + GPUShader *stereo_anaglyph[2]; GPUShader *frustum_line; GPUShader *frustum_solid; GPUShader *flat_color; @@ -855,25 +855,46 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) retval = GG.shaders.black_instancing; break; case GPU_SHADER_DRAW_FRAME_BUFFER: - if (!GG.shaders.draw_frame_buffer) - GG.shaders.draw_frame_buffer = GPU_shader_create( + if (!GG.shaders.draw_frame_buffer[0]) + GG.shaders.draw_frame_buffer[0] = GPU_shader_create( datatoc_gpu_shader_frame_buffer_vert_glsl, datatoc_gpu_shader_frame_buffer_frag_glsl, NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.draw_frame_buffer; + retval = GG.shaders.draw_frame_buffer[0]; + break; + case GPU_SHADER_DRAW_FRAME_BUFFER_SRGB: + if (!GG.shaders.draw_frame_buffer[1]) + GG.shaders.draw_frame_buffer[1] = GPU_shader_create( + datatoc_gpu_shader_frame_buffer_vert_glsl, datatoc_gpu_shader_frame_buffer_frag_glsl, + NULL, NULL, "#define COLOR_MANAGEMENT;\n", 0, 0, 0); + retval = GG.shaders.draw_frame_buffer[1]; break; case GPU_SHADER_STEREO_STIPPLE: - if (!GG.shaders.stereo_stipple) - GG.shaders.stereo_stipple = GPU_shader_create( + if (!GG.shaders.stereo_stipple[0]) + GG.shaders.stereo_stipple[0] = GPU_shader_create( datatoc_gpu_shader_frame_buffer_vert_glsl, datatoc_gpu_shader_frame_buffer_frag_glsl, NULL, NULL, "#define STIPPLE;\n", 0, 0, 0); - retval = GG.shaders.stereo_stipple; + retval = GG.shaders.stereo_stipple[0]; + break; + case GPU_SHADER_STEREO_STIPPLE_SRGB: + if (!GG.shaders.stereo_stipple[1]) + GG.shaders.stereo_stipple[1] = GPU_shader_create( + datatoc_gpu_shader_frame_buffer_vert_glsl, datatoc_gpu_shader_frame_buffer_frag_glsl, + NULL, NULL, "#define COLOR_MANAGEMENT;\n #define STIPPLE;\n", 0, 0, 0); + retval = GG.shaders.stereo_stipple[1]; break; case GPU_SHADER_STEREO_ANAGLYPH: - if (!GG.shaders.stereo_anaglyph) - GG.shaders.stereo_anaglyph = GPU_shader_create( + if (!GG.shaders.stereo_anaglyph[0]) + GG.shaders.stereo_anaglyph[0] = GPU_shader_create( datatoc_gpu_shader_frame_buffer_vert_glsl, datatoc_gpu_shader_frame_buffer_frag_glsl, NULL, NULL, "#define ANAGLYPH;\n", 0, 0, 0); - retval = GG.shaders.stereo_anaglyph; + retval = GG.shaders.stereo_anaglyph[0]; + break; + case GPU_SHADER_STEREO_ANAGLYPH_SRGB: + if (!GG.shaders.stereo_anaglyph[1]) + GG.shaders.stereo_anaglyph[1] = GPU_shader_create( + datatoc_gpu_shader_frame_buffer_vert_glsl, datatoc_gpu_shader_frame_buffer_frag_glsl, + NULL, NULL, "#define COLOR_MANAGEMENT;\n #define ANAGLYPH;\n", 0, 0, 0); + retval = GG.shaders.stereo_anaglyph[1]; break; case GPU_SHADER_FRUSTUM_LINE: if (!GG.shaders.frustum_line) @@ -1029,19 +1050,21 @@ void GPU_shader_free_builtin_shaders(void) GG.shaders.black_instancing = NULL; } - if (GG.shaders.draw_frame_buffer) { - GPU_shader_free(GG.shaders.draw_frame_buffer); - GG.shaders.draw_frame_buffer = NULL; - } + for (unsigned short i = 0; i < 2; ++i) { + if (GG.shaders.draw_frame_buffer[i]) { + GPU_shader_free(GG.shaders.draw_frame_buffer[i]); + GG.shaders.draw_frame_buffer[i] = NULL; + } - if (GG.shaders.stereo_stipple) { - GPU_shader_free(GG.shaders.stereo_stipple); - GG.shaders.stereo_stipple = NULL; - } + if (GG.shaders.stereo_stipple[i]) { + GPU_shader_free(GG.shaders.stereo_stipple[i]); + GG.shaders.stereo_stipple[i] = NULL; + } - if (GG.shaders.stereo_anaglyph) { - GPU_shader_free(GG.shaders.stereo_anaglyph); - GG.shaders.stereo_anaglyph = NULL; + if (GG.shaders.stereo_anaglyph[i]) { + GPU_shader_free(GG.shaders.stereo_anaglyph[i]); + GG.shaders.stereo_anaglyph[i] = NULL; + } } if (GG.shaders.frustum_line) { diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 373c4e3e915d..7cf0f07566ed 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -153,7 +153,7 @@ static GPUTexture *GPU_texture_create_nD( format = GL_RGBA; switch (hdr_type) { case GPU_HDR_NONE: - internalformat = GL_RGBA8; + internalformat = GL_RGBA12; break; /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ case GPU_HDR_HALF_FLOAT: diff --git a/source/blender/gpu/shaders/gpu_shader_frame_buffer_frag.glsl b/source/blender/gpu/shaders/gpu_shader_frame_buffer_frag.glsl index 470dec7e54dc..36d651bb4706 100644 --- a/source/blender/gpu/shaders/gpu_shader_frame_buffer_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_frame_buffer_frag.glsl @@ -15,6 +15,22 @@ uniform sampler2D depthtex; uniform int stippleid; #endif +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) + return (c < 0.0) ? 0.0 : c * 12.92; + else + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; +} + +void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; +} + void main() { vec2 co = gl_TexCoord[0].xy; @@ -45,4 +61,8 @@ void main() gl_FragDepth = texture2D(depthtex, co).x; # endif #endif + +#ifdef COLOR_MANAGEMENT + linearrgb_to_srgb(gl_FragColor, gl_FragColor); +#endif } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 32747d34a86f..1b0982ed4055 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -873,6 +873,8 @@ typedef struct GameData { /* Scene LoD */ short lodflag, pad2; int scehysteresis; + + short colorManagement, pad3[3]; } GameData; /* GameData.stereoflag */ @@ -916,7 +918,6 @@ typedef struct GameData { #define GAME_GLSL_NO_EXTRA_TEX (1 << 11) #define GAME_IGNORE_DEPRECATION_WARNINGS (1 << 12) #define GAME_SHOW_MOUSE (1 << 14) -#define GAME_GLSL_NO_COLOR_MANAGEMENT (1 << 15) #define GAME_SHOW_OBSTACLE_SIMULATION (1 << 16) #ifdef DNA_DEPRECATED # define GAME_SHOW_BOUNDING_BOX (1 << 18) @@ -960,6 +961,12 @@ enum { GAME_SOLVER_MLCP_LEMKE, }; +/* GameData.colorManagement */ +enum { + GAME_COLOR_MANAGEMENT_LINEAR = 0, + GAME_COLOR_MANAGEMENT_SRGB +}; + /* UV Paint */ /* ToolSettings.uv_sculpt_settings */ #define UV_SCULPT_LOCK_BORDERS 1 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d9bc4d35265a..1da1be107c0e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4481,6 +4481,12 @@ static void rna_def_scene_game_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem color_management_items[] = { + {GAME_COLOR_MANAGEMENT_LINEAR, "COLOR_MANAGEMENT_LINEAR", 0, "Linear", "Linear color space"}, + {GAME_COLOR_MANAGEMENT_SRGB, "COLOR_MANAGEMENT_SRGB", 0, "sRGB", "sRGB color space"}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem solver_items[] = { {GAME_SOLVER_SEQUENTIAL, "SOLVER_SEQUENTIAL", 0, "Sequential", "Sequential physics solver, default solver"}, {GAME_SOLVER_NNCG, "SOLVER_NNGC", 0, "NNGC", "NNGC physics solver"}, @@ -4584,6 +4590,12 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bits", "Display bit depth of full screen display"); RNA_def_property_update(prop, NC_SCENE, NULL); + prop = RNA_def_property(srna, "color_management", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "colorManagement"); + RNA_def_property_enum_items(prop, color_management_items); + RNA_def_property_ui_text(prop, "Color Management", "The color managment of the display"); + RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_glsl_update"); + prop = RNA_def_property(srna, "exit_key", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "exitkey"); RNA_def_property_enum_items(prop, rna_enum_event_type_items); @@ -4894,11 +4906,6 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "GLSL Nodes", "Use nodes for GLSL rendering"); RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_glsl_update"); - prop = RNA_def_property(srna, "use_glsl_color_management", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_GLSL_NO_COLOR_MANAGEMENT); - RNA_def_property_ui_text(prop, "GLSL Color Management", "Use color management for GLSL rendering"); - RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_glsl_update"); - prop = RNA_def_property(srna, "use_glsl_extra_textures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_GLSL_NO_EXTRA_TEX); RNA_def_property_ui_text(prop, "GLSL Extra Textures", diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index d38cfa7d83b7..66bbbb220c47 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1012,10 +1012,9 @@ static KX_GameObject *BL_GameObjectFromBlenderObject(Object *ob, KX_Scene *kxsce case OB_FONT: { - bool do_color_management = BKE_scene_check_color_management_enabled(blenderscene); // Font objects have no bounding box. KX_FontObject *fontobj = new KX_FontObject(kxscene, KX_Scene::m_callbacks, rendertools, - kxscene->GetBoundingBoxManager(), ob, do_color_management); + kxscene->GetBoundingBoxManager(), ob); gameobj = fontobj; kxscene->GetFontList()->Add(CM_AddRef(fontobj)); diff --git a/source/gameengine/Converter/BL_Converter.cpp b/source/gameengine/Converter/BL_Converter.cpp index 3f28ae59dff8..259c971c6fa4 100644 --- a/source/gameengine/Converter/BL_Converter.cpp +++ b/source/gameengine/Converter/BL_Converter.cpp @@ -711,6 +711,11 @@ void BL_Converter::FinalizeSceneData(const BL_SceneConverter& converter) for (KX_BlenderMaterial *mat : converter.m_materials) { mat->InitShader(); } + + KX_WorldInfo *world = converter.GetScene()->GetWorldInfo(); + if (world) { + world->ReloadMaterial(); + } } /** This function merges a mesh from the current scene into another main diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 4d5da9b153f4..98dc0c6454c8 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -123,7 +123,9 @@ void BL_BlenderShader::ReloadMaterial() GPU_material_free(&m_mat->gpumaterialinstancing); } - m_gpuMat = (m_mat) ? GPU_material_from_blender(m_blenderScene, m_mat, false, UseInstancing()) : nullptr; + GPUMaterialFlag flags = (GPUMaterialFlag) + (GPU_MATERIAL_NO_COLOR_MANAGEMENT | (UseInstancing() ? GPU_MATERIAL_INSTANCING : 0)); + m_gpuMat = (m_mat) ? GPU_material_from_blender(m_blenderScene, m_mat, flags) : nullptr; m_materialUpdateServer->NotifyUpdate(RAS_IMaterial::SHADER_MODIFIED); } diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp index 62c96ab5823b..27a972b34b5f 100644 --- a/source/gameengine/Ketsji/KX_FontObject.cpp +++ b/source/gameengine/Ketsji/KX_FontObject.cpp @@ -85,14 +85,12 @@ KX_FontObject::KX_FontObject(void *sgReplicationInfo, SG_Callbacks callbacks, RAS_Rasterizer *rasterizer, RAS_BoundingBoxManager *boundingBoxManager, - Object *ob, - bool do_color_management) + Object *ob) :KX_GameObject(sgReplicationInfo, callbacks), m_object(ob), m_dpi(72), m_resolution(1.0f), - m_rasterizer(rasterizer), - m_do_color_management(do_color_management) + m_rasterizer(rasterizer) { Curve *text = static_cast (ob->data); m_fsize = text->fsize; @@ -150,15 +148,6 @@ void KX_FontObject::UpdateBuckets() m_sgNode->ClearDirty(SG_Node::DIRTY_RENDER); } - // Font Objects don't use the glsl shader, this color management code is copied from gpu_shader_material.glsl - float color[4]; - if (m_do_color_management) { - linearrgb_to_srgb_v4(color, m_objectColor.Data()); - } - else { - m_objectColor.Pack(color); - } - // HARDCODED MULTIPLICATION FACTOR - this will affect the render resolution directly const float RES = BGE_FONT_RES * m_resolution; @@ -171,7 +160,7 @@ void KX_FontObject::UpdateBuckets() mt::vec3 spacing = NodeGetWorldOrientation() * mt::vec3(0.0f, m_fsize * m_line_spacing, 0.0f) * NodeGetWorldScaling()[1]; textUser->SetLayer(m_layer); - textUser->SetColor(mt::vec4(color)); + textUser->SetColor(m_objectColor); textUser->SetFontId(m_fontid); textUser->SetSize(size); textUser->SetDpi(m_dpi); diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h index f2d8d67db503..5ac5581589e3 100644 --- a/source/gameengine/Ketsji/KX_FontObject.h +++ b/source/gameengine/Ketsji/KX_FontObject.h @@ -44,8 +44,7 @@ class KX_FontObject : public KX_GameObject SG_Callbacks callbacks, RAS_Rasterizer *rasterizer, RAS_BoundingBoxManager *boundingBoxManager, - Object *ob, - bool do_color_management); + Object *ob); virtual ~KX_FontObject(); @@ -87,8 +86,6 @@ class KX_FontObject : public KX_GameObject /// needed for drawing routine class RAS_Rasterizer *m_rasterizer; - bool m_do_color_management; - void GetTextAabb(mt::vec2& min, mt::vec2& max); #ifdef WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 883c90b02a1c..80f5fba3d4b0 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -716,11 +716,11 @@ void KX_KetsjiEngine::Render() if (renderData.m_renderPerEye) { RAS_OffScreen *leftofs = m_rasterizer->GetOffScreen(renderData.m_frameDataList[0].m_ofsType); RAS_OffScreen *rightofs = m_rasterizer->GetOffScreen(renderData.m_frameDataList[1].m_ofsType); - m_rasterizer->DrawStereoOffScreen(m_canvas, leftofs, rightofs, renderData.m_stereoMode); + m_rasterizer->DrawStereoOffScreenToScreen(m_canvas, leftofs, rightofs, renderData.m_stereoMode); } // Else simply draw the off screen to screen. else { - m_rasterizer->DrawOffScreen(m_canvas, m_rasterizer->GetOffScreen(renderData.m_frameDataList[0].m_ofsType)); + m_rasterizer->DrawOffScreenToScreen(m_canvas, m_rasterizer->GetOffScreen(renderData.m_frameDataList[0].m_ofsType)); } EndFrame(); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index aa1d29c47bcf..9b7d5409a46f 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1123,6 +1123,10 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *, if (scene->GetBucketManager()) { scene->GetBucketManager()->ReloadMaterials(); } + KX_WorldInfo *world = scene->GetWorldInfo(); + if (world) { + world->ReloadMaterial(); + } } } } diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index 801350b073f9..e2ca962ee2dd 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -46,7 +46,6 @@ #include "BLI_math.h" -#include "BKE_global.h" #include "BKE_scene.h" /* end of blender include block */ @@ -55,7 +54,6 @@ KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld) { if (blenderworld) { m_name = blenderworld->id.name + 2; - m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); m_hasworld = true; m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); m_hasEnvLight = ((blenderworld->mode) & WO_ENV_LIGHT ? true : false); @@ -101,6 +99,16 @@ std::string KX_WorldInfo::GetName() return m_name; } +void KX_WorldInfo::ReloadMaterial() +{ + if (m_hasworld && m_scene->world->skytype & (WO_SKYBLEND | WO_SKYPAPER | WO_SKYREAL)) { + m_gpuMat = GPU_material_world(m_scene, m_scene->world, GPU_MATERIAL_NO_COLOR_MANAGEMENT); + } + else { + m_gpuMat = nullptr; + } +} + bool KX_WorldInfo::hasWorld() { return m_hasworld; @@ -144,29 +152,11 @@ void KX_WorldInfo::setRange(float range) void KX_WorldInfo::setMistColor(const mt::vec3& mistcolor) { m_mistcolor = mistcolor; - - if (m_do_color_management) { - float col[3]; - linearrgb_to_srgb_v3_v3(col, m_mistcolor.Data()); - m_con_mistcolor = mt::vec3(col); - } - else { - m_con_mistcolor = m_mistcolor; - } } void KX_WorldInfo::setAmbientColor(const mt::vec3& ambientcolor) { m_ambientcolor = ambientcolor; - - if (m_do_color_management) { - float col[3]; - linearrgb_to_srgb_v3_v3(col, m_ambientcolor.Data()); - m_con_ambientcolor = mt::vec3(col); - } - else { - m_con_ambientcolor = m_ambientcolor; - } } void KX_WorldInfo::UpdateBackGround(RAS_Rasterizer *rasty) @@ -189,13 +179,13 @@ void KX_WorldInfo::UpdateBackGround(RAS_Rasterizer *rasty) void KX_WorldInfo::UpdateWorldSettings(RAS_Rasterizer *rasty) { if (m_hasworld) { - rasty->SetAmbientColor(m_con_ambientcolor); + rasty->SetAmbientColor(m_ambientcolor); GPU_ambient_update_color(m_ambientcolor.Data()); GPU_update_exposure_range(m_exposure, m_range); GPU_update_envlight_energy(m_envLightEnergy); if (m_hasmist) { - rasty->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); + rasty->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor.Data()); GPU_mist_update_enable(true); } @@ -208,11 +198,9 @@ void KX_WorldInfo::UpdateWorldSettings(RAS_Rasterizer *rasty) void KX_WorldInfo::RenderBackground(RAS_Rasterizer *rasty) { if (m_hasworld) { - if (m_scene->world->skytype & (WO_SKYBLEND | WO_SKYPAPER | WO_SKYREAL)) { - GPUMaterial *gpumat = GPU_material_world(m_scene, m_scene->world); - + if (m_gpuMat) { static float texcofac[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; - GPU_material_bind(gpumat, m_scene->lay, 1.0f, false, rasty->GetViewMatrix().Data(), + GPU_material_bind(m_gpuMat, m_scene->lay, 1.0f, false, rasty->GetViewMatrix().Data(), rasty->GetViewInvMatrix().Data(), texcofac, false); rasty->SetFrontFace(true); @@ -223,26 +211,16 @@ void KX_WorldInfo::RenderBackground(RAS_Rasterizer *rasty) rasty->SetDepthFunc(RAS_Rasterizer::RAS_LEQUAL); - GPU_material_unbind(gpumat); + GPU_material_unbind(m_gpuMat); } else { - if (m_do_color_management) { - float srgbcolor[4]; - linearrgb_to_srgb_v4(srgbcolor, m_horizoncolor.Data()); - rasty->SetClearColor(srgbcolor[0], srgbcolor[1], srgbcolor[2], srgbcolor[3]); - } - else { - rasty->SetClearColor(m_horizoncolor[0], m_horizoncolor[1], m_horizoncolor[2], m_horizoncolor[3]); - } + rasty->SetClearColor(m_horizoncolor[0], m_horizoncolor[1], m_horizoncolor[2], m_horizoncolor[3]); rasty->Clear(RAS_Rasterizer::RAS_COLOR_BUFFER_BIT); } } // Else render a dummy gray background. else { - /* Grey color computed by linearrgb_to_srgb_v3_v3 with a color of - * 0.050, 0.050, 0.050 (the default world horizon color). - */ - rasty->SetClearColor(0.247784f, 0.247784f, 0.247784f, 1.0f); + rasty->SetClearColor(0.05f, 0.05f, 0.05f, 1.0f); rasty->Clear(RAS_Rasterizer::RAS_COLOR_BUFFER_BIT); } } diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 523a3daef0e7..7f58b22c34e0 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -40,6 +40,7 @@ void KX_WorldInfo_Mathutils_Callback_Init(void); #endif class RAS_Rasterizer; +struct GPUMaterial; struct Scene; struct World; @@ -49,7 +50,7 @@ class KX_WorldInfo : public EXP_Value, public mt::SimdClassAllocator std::string m_name; Scene *m_scene; - bool m_do_color_management; + GPUMaterial *m_gpuMat; bool m_hasworld; bool m_hasmist; bool m_hasEnvLight; @@ -65,8 +66,11 @@ class KX_WorldInfo : public EXP_Value, public mt::SimdClassAllocator mt::vec4 m_horizoncolor; mt::vec4 m_zenithcolor; mt::vec3 m_ambientcolor; - mt::vec3 m_con_mistcolor; - mt::vec3 m_con_ambientcolor; + + struct { + mt::vec3 horizonColor; + mt::vec3 zenithColor; + } m_savedData; public: /** @@ -81,12 +85,9 @@ class KX_WorldInfo : public EXP_Value, public mt::SimdClassAllocator KX_WorldInfo(Scene *blenderscene, World *blenderworld); ~KX_WorldInfo(); - struct { - mt::vec3 horizonColor; - mt::vec3 zenithColor; - } m_savedData; - virtual std::string GetName(); + + void ReloadMaterial(); bool hasWorld(); void setMistStart(float d); void setMistDistance(float d); diff --git a/source/gameengine/Launcher/LA_Launcher.cpp b/source/gameengine/Launcher/LA_Launcher.cpp index 04e6e4652f40..a9b1b188b19c 100644 --- a/source/gameengine/Launcher/LA_Launcher.cpp +++ b/source/gameengine/Launcher/LA_Launcher.cpp @@ -173,6 +173,11 @@ void LA_Launcher::InitEngine() m_rasterizer = new RAS_Rasterizer(); // Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI + static const RAS_Rasterizer::ColorManagement colorManagementTable[] = { + RAS_Rasterizer::RAS_COLOR_MANAGEMENT_LINEAR, // GAME_COLOR_MANAGEMENT_LINEAR + RAS_Rasterizer::RAS_COLOR_MANAGEMENT_SRGB // GAME_COLOR_MANAGEMENT_SRGB + }; + m_rasterizer->SetColorManagment(colorManagementTable[gm.colorManagement]); m_rasterizer->SetStereoMode(m_stereoMode); m_rasterizer->SetEyeSeparation(m_startScene->gm.eyeseparation); m_rasterizer->SetDrawingMode(GetRasterizerDrawMode()); diff --git a/source/gameengine/Rasterizer/RAS_Rasterizer.cpp b/source/gameengine/Rasterizer/RAS_Rasterizer.cpp index 48f53abd5fd6..e06e687fe170 100644 --- a/source/gameengine/Rasterizer/RAS_Rasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_Rasterizer.cpp @@ -194,6 +194,14 @@ RAS_Rasterizer::OffScreenType RAS_Rasterizer::NextRenderOffScreen(RAS_Rasterizer } } +// Each shader used to draw the offscreen to screen by color management. +GPUBuiltinShader offScreenToScreenShaderTable[RAS_Rasterizer::RAS_SHADER_TO_SCREEN_MAX][RAS_Rasterizer::RAS_COLOR_MANAGEMENT_MAX] = { + // Linear, sRGB + {GPU_SHADER_DRAW_FRAME_BUFFER, GPU_SHADER_DRAW_FRAME_BUFFER_SRGB}, // Normal + {GPU_SHADER_STEREO_STIPPLE, GPU_SHADER_STEREO_STIPPLE_SRGB}, // Stereo stipple + {GPU_SHADER_STEREO_ANAGLYPH, GPU_SHADER_STEREO_ANAGLYPH_SRGB} // Stereo anaglyph +}; + RAS_Rasterizer::RAS_Rasterizer() :m_time(0.0f), m_ambient(mt::zero3), @@ -208,6 +216,7 @@ RAS_Rasterizer::RAS_Rasterizer() m_focallength(0.0f), m_setfocallength(false), m_noOfScanlines(32), + m_colorManagement(RAS_COLOR_MANAGEMENT_LINEAR), m_motionblur(0), m_motionblurvalue(-1.0f), m_clientobject(nullptr), @@ -222,8 +231,6 @@ RAS_Rasterizer::RAS_Rasterizer() m_numgllights = m_impl->GetNumLights(); - InitOverrideShadersInterface(); - m_state.frontFace = -1; m_state.cullFace = -1; m_state.polyOffset[0] = -1.0f; @@ -283,6 +290,8 @@ void RAS_Rasterizer::Init() SetColorMask(true, true, true, true); m_impl->Init(); + + InitOverrideShadersInterface(); } void RAS_Rasterizer::Exit() @@ -427,9 +436,6 @@ void RAS_Rasterizer::DrawOffScreen(RAS_OffScreen *srcOffScreen, RAS_OffScreen *d GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_DRAW_FRAME_BUFFER); GPU_shader_bind(shader); - OverrideShaderDrawFrameBufferInterface *interface = (OverrideShaderDrawFrameBufferInterface *)GPU_shader_get_interface(shader); - GPU_shader_uniform_int(shader, interface->colorTexLoc, 0); - DrawOverlayPlane(); GPU_shader_unbind(); @@ -438,7 +444,7 @@ void RAS_Rasterizer::DrawOffScreen(RAS_OffScreen *srcOffScreen, RAS_OffScreen *d } } -void RAS_Rasterizer::DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen) +void RAS_Rasterizer::DrawOffScreenToScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen) { if (offScreen->GetSamples() > 0) { offScreen = offScreen->Blit(GetOffScreen(RAS_OFFSCREEN_EYE_LEFT1), true, false); @@ -452,13 +458,24 @@ void RAS_Rasterizer::DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen SetDepthFunc(RAS_ALWAYS); RAS_OffScreen::RestoreScreen(); - DrawOffScreen(offScreen, nullptr); + + offScreen->BindColorTexture(0); + + GPUShader *shader = + GPU_shader_get_builtin_shader(offScreenToScreenShaderTable[RAS_SHADER_TO_SCREEN_NORMAL][m_colorManagement]); + GPU_shader_bind(shader); + + DrawOverlayPlane(); + + GPU_shader_unbind(); + + offScreen->UnbindColorTexture(); SetDepthFunc(RAS_LEQUAL); } -void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen, - StereoMode stereoMode) +void RAS_Rasterizer::DrawStereoOffScreenToScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, + RAS_OffScreen *rightOffScreen, StereoMode stereoMode) { if (leftOffScreen->GetSamples() > 0) { // Then leftOffScreen == RAS_OFFSCREEN_EYE_LEFT0. @@ -480,44 +497,28 @@ void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *lef RAS_OffScreen::RestoreScreen(); if (stereoMode == RAS_STEREO_VINTERLACE || stereoMode == RAS_STEREO_INTERLACED) { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_STIPPLE); + GPUShader *shader = + GPU_shader_get_builtin_shader(offScreenToScreenShaderTable[RAS_SHADER_TO_SCREEN_STEREO_STIPPLE][m_colorManagement]); GPU_shader_bind(shader); OverrideShaderStereoStippleInterface *interface = (OverrideShaderStereoStippleInterface *)GPU_shader_get_interface(shader); - - leftOffScreen->BindColorTexture(0); - rightOffScreen->BindColorTexture(1); - - GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); - GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); GPU_shader_uniform_int(shader, interface->stippleIdLoc, (stereoMode == RAS_STEREO_INTERLACED) ? 1 : 0); - - DrawOverlayPlane(); - - GPU_shader_unbind(); - - leftOffScreen->UnbindColorTexture(); - rightOffScreen->UnbindColorTexture(); } else if (stereoMode == RAS_STEREO_ANAGLYPH) { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_ANAGLYPH); + GPUShader *shader = + GPU_shader_get_builtin_shader(offScreenToScreenShaderTable[RAS_SHADER_TO_SCREEN_STEREO_ANAGLYPH][m_colorManagement]); GPU_shader_bind(shader); + } - OverrideShaderStereoAnaglyph *interface = (OverrideShaderStereoAnaglyph *)GPU_shader_get_interface(shader); - - leftOffScreen->BindColorTexture(0); - rightOffScreen->BindColorTexture(1); - - GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); - GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); + leftOffScreen->BindColorTexture(0); + rightOffScreen->BindColorTexture(1); - DrawOverlayPlane(); + DrawOverlayPlane(); - GPU_shader_unbind(); + leftOffScreen->UnbindColorTexture(); + rightOffScreen->UnbindColorTexture(); - leftOffScreen->UnbindColorTexture(); - rightOffScreen->UnbindColorTexture(); - } + GPU_shader_unbind(); SetDepthFunc(RAS_LEQUAL); } @@ -989,6 +990,11 @@ void RAS_Rasterizer::SetInvertFrontFace(bool invert) m_invertFrontFace = invert; } +void RAS_Rasterizer::SetColorManagment(ColorManagement colorManagement) +{ + m_colorManagement = colorManagement; +} + void RAS_Rasterizer::SetAnisotropicFiltering(short level) { GPU_set_anisotropic(G.main, (float)level); @@ -1042,41 +1048,60 @@ void RAS_Rasterizer::InitOverrideShadersInterface() // Find uniform location for FBO shaders. // Draw frame buffer shader. - { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_DRAW_FRAME_BUFFER); - if (!GPU_shader_get_interface(shader)) { - OverrideShaderDrawFrameBufferInterface *interface = (OverrideShaderDrawFrameBufferInterface *)MEM_mallocN(sizeof(OverrideShaderDrawFrameBufferInterface), "OverrideShaderDrawFrameBufferInterface"); + for (unsigned short i = 0; i < RAS_COLOR_MANAGEMENT_MAX; ++i) { + { + GPUShader *shader = + GPU_shader_get_builtin_shader(offScreenToScreenShaderTable[RAS_SHADER_TO_SCREEN_NORMAL][i]); + if (!GPU_shader_get_interface(shader)) { + OverrideShaderDrawFrameBufferInterface *interface = (OverrideShaderDrawFrameBufferInterface *)MEM_mallocN(sizeof(OverrideShaderDrawFrameBufferInterface), "OverrideShaderDrawFrameBufferInterface"); + + interface->colorTexLoc = GPU_shader_get_uniform(shader, "colortex"); - interface->colorTexLoc = GPU_shader_get_uniform(shader, "colortex"); + GPU_shader_bind(shader); + GPU_shader_uniform_int(shader, interface->colorTexLoc, 0); + GPU_shader_unbind(); - GPU_shader_set_interface(shader, interface); + GPU_shader_set_interface(shader, interface); + } } - } - // Stipple stereo shader. - { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_STIPPLE); - if (!GPU_shader_get_interface(shader)) { - OverrideShaderStereoStippleInterface *interface = (OverrideShaderStereoStippleInterface *)MEM_mallocN(sizeof(OverrideShaderStereoStippleInterface), "OverrideShaderStereoStippleInterface"); + // Stipple stereo shader. + { + GPUShader *shader = + GPU_shader_get_builtin_shader(offScreenToScreenShaderTable[RAS_SHADER_TO_SCREEN_STEREO_STIPPLE][i]); + if (!GPU_shader_get_interface(shader)) { + OverrideShaderStereoStippleInterface *interface = (OverrideShaderStereoStippleInterface *)MEM_mallocN(sizeof(OverrideShaderStereoStippleInterface), "OverrideShaderStereoStippleInterface"); - interface->leftEyeTexLoc = GPU_shader_get_uniform(shader, "lefteyetex"); - interface->rightEyeTexLoc = GPU_shader_get_uniform(shader, "righteyetex"); - interface->stippleIdLoc = GPU_shader_get_uniform(shader, "stippleid"); + interface->leftEyeTexLoc = GPU_shader_get_uniform(shader, "lefteyetex"); + interface->rightEyeTexLoc = GPU_shader_get_uniform(shader, "righteyetex"); + interface->stippleIdLoc = GPU_shader_get_uniform(shader, "stippleid"); - GPU_shader_set_interface(shader, interface); + GPU_shader_bind(shader); + GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); + GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); + GPU_shader_unbind(); + + GPU_shader_set_interface(shader, interface); + } } - } - // Anaglyph stereo shader. - { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_ANAGLYPH); - if (!GPU_shader_get_interface(shader)) { - OverrideShaderStereoAnaglyph *interface = (OverrideShaderStereoAnaglyph *)MEM_mallocN(sizeof(OverrideShaderStereoAnaglyph), "OverrideShaderStereoAnaglyph"); + // Anaglyph stereo shader. + { + GPUShader *shader = + GPU_shader_get_builtin_shader(offScreenToScreenShaderTable[RAS_SHADER_TO_SCREEN_STEREO_ANAGLYPH][i]); + if (!GPU_shader_get_interface(shader)) { + OverrideShaderStereoAnaglyph *interface = (OverrideShaderStereoAnaglyph *)MEM_mallocN(sizeof(OverrideShaderStereoAnaglyph), "OverrideShaderStereoAnaglyph"); + + interface->leftEyeTexLoc = GPU_shader_get_uniform(shader, "lefteyetex"); + interface->rightEyeTexLoc = GPU_shader_get_uniform(shader, "righteyetex"); - interface->leftEyeTexLoc = GPU_shader_get_uniform(shader, "lefteyetex"); - interface->rightEyeTexLoc = GPU_shader_get_uniform(shader, "righteyetex"); + GPU_shader_bind(shader); + GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); + GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); + GPU_shader_unbind(); - GPU_shader_set_interface(shader, interface); + GPU_shader_set_interface(shader, interface); + } } } } diff --git a/source/gameengine/Rasterizer/RAS_Rasterizer.h b/source/gameengine/Rasterizer/RAS_Rasterizer.h index 0c3f94e0818c..e29c0437d607 100644 --- a/source/gameengine/Rasterizer/RAS_Rasterizer.h +++ b/source/gameengine/Rasterizer/RAS_Rasterizer.h @@ -219,6 +219,19 @@ class RAS_Rasterizer : public mt::SimdClassAllocator RAS_HDR_MAX }; + enum ColorManagement { + RAS_COLOR_MANAGEMENT_LINEAR = 0, + RAS_COLOR_MANAGEMENT_SRGB, + RAS_COLOR_MANAGEMENT_MAX + }; + + enum ShaderToScreen { + RAS_SHADER_TO_SCREEN_NORMAL = 0, + RAS_SHADER_TO_SCREEN_STEREO_STIPPLE, + RAS_SHADER_TO_SCREEN_STEREO_ANAGLYPH, + RAS_SHADER_TO_SCREEN_MAX + }; + /** Return the output frame buffer normally used for the input frame buffer * index in case of filters render. * \param index The input frame buffer, can be a non-filter frame buffer. @@ -297,6 +310,8 @@ class RAS_Rasterizer : public mt::SimdClassAllocator bool m_setfocallength; int m_noOfScanlines; + ColorManagement m_colorManagement; + /* motion blur */ unsigned short m_motionblur; float m_motionblurvalue; @@ -441,7 +456,7 @@ class RAS_Rasterizer : public mt::SimdClassAllocator * \param canvas The canvas containing the screen viewport. * \param index The off screen index to read from. */ - void DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen); + void DrawOffScreenToScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen); /** Draw each stereo off screen to screen. * \param canvas The canvas containing the screen viewport. @@ -449,7 +464,7 @@ class RAS_Rasterizer : public mt::SimdClassAllocator * \param righteyeindex The right off screen index. * \param stereoMode The stereo category. */ - void DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen, StereoMode stereoMode); + void DrawStereoOffScreenToScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen, StereoMode stereoMode); /** * GetRenderArea computes the render area from the 2d canvas. @@ -647,6 +662,8 @@ class RAS_Rasterizer : public mt::SimdClassAllocator void SetInvertFrontFace(bool invert); + void SetColorManagment(ColorManagement colorManagement); + void SetAnisotropicFiltering(short level); short GetAnisotropicFiltering(); diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index 380c9724dade..b56dc458e28b 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -62,7 +62,7 @@ ExpDesc InvalidColorChannelDesc(InvalidColorChannel, "Invalid or too many color ExpDesc InvalidImageModeDesc(InvalidImageMode, "Invalid image mode, only RGBA and BGRA are supported"); // constructor -ImageBase::ImageBase(bool staticSrc) :m_image(nullptr), m_imgSize(0), m_internalFormat(GL_RGBA8), +ImageBase::ImageBase(bool staticSrc) :m_image(nullptr), m_imgSize(0), m_internalFormat(GL_RGBA12), m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false), m_zbuff(false), m_depth(false), diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index c13b60c33525..dd0cd6489b9a 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -104,7 +104,7 @@ ImageRender::ImageRender(KX_Scene *scene, KX_Camera *camera, unsigned int width, } else { type = GPU_HDR_NONE; - m_internalFormat = GL_RGBA8; + m_internalFormat = GL_RGBA12; } m_offScreen.reset(new RAS_OffScreen(m_width, m_height, m_samples, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, nullptr, RAS_Rasterizer::RAS_OFFSCREEN_CUSTOM)); @@ -878,7 +878,7 @@ ImageRender::ImageRender(KX_Scene *scene, KX_GameObject *observer, KX_GameObject } else { type = GPU_HDR_NONE; - m_internalFormat = GL_RGBA8; + m_internalFormat = GL_RGBA12; } m_offScreen.reset(new RAS_OffScreen(m_width, m_height, m_samples, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, nullptr, RAS_Rasterizer::RAS_OFFSCREEN_CUSTOM));