Skip to content

Commit

Permalink
UPBGE: Implement infinite planar maps and refactor cube maps.
Browse files Browse the repository at this point in the history
Infinite planar reflection and refraction is a technique inspired from the
martinsh's works.
This technique consists to render the scene with the same projection matrix as
the scene camera but with a position and an orientation different allowing to
render the part wanted for the reflection or the refraction.

To accept the planar map, the system rendering the cube maps needed to be
refactored. Indeed the system was too detailed and no general to the cube maps
and the planar map.

This new system work with a base class, the texture renderer. This texture
renderer contains some faces to render, these faces are containing a frame
buffer attached to the texture using the planar or cube map. Upon the texture
renderer, two specialization exists, the cube map KX_CubeMap and KX_PlanarMap,
theirs goal is to defines the faces and to modify the camera used for the
render.

Two categories of texture renderer can be defined, the viewport independents and
the viewport dependents. Cube maps are viewport independents because they use
their own camera projection, position and rotation, but it is no the case for
planar maps. The planar map need to access the setting to create the projection
matrix as the current camera rendering the scene, also they need the camera
position and orientation.

These two categories are stored into KX_TextureRendererMananegr (as
KX_CubeMapManager previously) under the list m_renderers[2] accessed with the
index VIEWPORT_DEPENDENT and VIEWPORT_INDEPENDENT. Finally two call to render
the texture renderers is made in the frame render, one before render all the
scenes for the independents and other per scene for the dependents.

One of the goal of the specialization of cube maps and planar maps was to define
the proper setting for the camera doing the render. To do so, two virtual
function were defined: SetupCamera and SetupCameraFace. The first function
define the settings shared between all the faces to render (e.g for cube maps
the camera position). The second function define the setting unique per faces.

After setup the camera settings shared per face, the projection matrix is
computed or/and get thanks to the fnction GetProjection, this function take
arguments for the viewport dependent renderer as the current scene camera the
viewport and area dimension.

The attributes shared between the KX_CubeMap and the KX_PlanarMap are exposed
into the base python proxy KX_TextureRenderer, only KX_PlanarMap use an extra
attribute called "normal" for the mirror normal.

In the UI some changes were made. To define a planar map the user have to set
the mapping to "Plane" instead of "Cube" in an environment map under "Realtime".
As the planar map have to be rendered differently to make refraction a menu is
exposed to choose reflection or refraction.

In GLSL, only a function to read the planar map texture according to the
viewport is added, it is named mtex_image_refl.
  • Loading branch information
youle31 authored and panzergame committed Feb 21, 2017
1 parent 935feda commit acdbcc2
Show file tree
Hide file tree
Showing 37 changed files with 1,626 additions and 877 deletions.
2 changes: 2 additions & 0 deletions release/scripts/startup/bl_ui/properties_texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ def draw(self, context):
layout.template_ID(tex, "image", new="image.new", open="image.open")
layout.template_image(tex, "image", tex.image_user, compact=True)
layout.prop(env, "filtering")
if env.mapping == 'PLANE':
layout.prop(env, "mode")
layout.prop(env, "mapping")
if env.mapping == 'PLANE':
layout.prop(env, "zoom")
Expand Down
19 changes: 16 additions & 3 deletions source/blender/gpu/intern/gpu_material.c
Original file line number Diff line number Diff line change
Expand Up @@ -1398,14 +1398,27 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false),
GPU_select_uniform(&mtex->lodbias, GPU_DYNAMIC_TEX_LODBIAS, NULL, ma), &tin, &trgb);
}
else {
GPU_link(mat, "mtex_cube_map_refl_refr",
GPU_cube_map(tex->ima, &tex->iuser, false), shi->view, shi->vn,
else if (tex->type == TEX_ENVMAP) {
if (tex->env->type == ENV_PLANE) {
GPU_link(mat, "mtex_image_refl",
GPU_builtin(GPU_VIEW_POSITION),
GPU_builtin(GPU_CAMERA_TEXCO_FACTORS),
texco,
GPU_image(tex->ima, &tex->iuser, false),
GPU_select_uniform(&mtex->lodbias, GPU_DYNAMIC_TEX_LODBIAS, NULL, ma),
GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_VIEW_MATRIX),
shi->view, shi->vn, &tin, &trgb);
}
else if (tex->env->type == ENV_CUBE) {
GPU_link(mat, "mtex_cube_map_refl_refr",
GPU_cube_map(tex->ima, &tex->iuser, false), shi->view, shi->vn,
GPU_select_uniform(&mtex->lodbias, GPU_DYNAMIC_TEX_LODBIAS, NULL, ma),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
GPU_select_uniform(&mtex->ior, GPU_DYNAMIC_TEX_IOR, NULL, ma),
GPU_select_uniform(&mtex->refrratio, GPU_DYNAMIC_TEX_REFRRATIO, NULL, ma),
&tin, &trgb);
}
}
rgbnor = TEX_RGB;

Expand Down
16 changes: 16 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_material.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,22 @@ void mtex_image(vec3 texco, sampler2D ima, float lodbias, out float value, out v
value = 1.0;
}

void mtex_image_refl(vec3 I, vec4 camerafac, vec3 texco, sampler2D ima, float lodbias, mat4 objectmatrix, mat4 viewmatrix, vec3 vp, vec3 vn, out float value, out vec4 color)
{
vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
vec3 window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);

vec3 Z = normalize(vec3(viewmatrix * objectmatrix * vec4( 0.0, 0.0, 1.0, 0.0)));

vec3 reflecteddirection = reflect(vp, vn) - reflect(vp, Z);

// 0.25 is an artistic constant, normal map distortion needs to be scaled down to give proper results
vec2 uv = window.xy + vec2(reflecteddirection.x, reflecteddirection.y) * 0.25;

color = texture2D(ima, uv, lodbias);
value = 1.0;
}

void mtex_normal(vec3 texco, sampler2D ima, float lodbias, out vec3 normal)
{
// The invert of the red channel is to make
Expand Down
5 changes: 5 additions & 0 deletions source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
varying vec3 varposition;
varying vec3 varnormal;

varying float gl_ClipDistance[6];

/* Color, keep in sync with: gpu_shader_vertex.glsl */

Expand Down Expand Up @@ -79,3 +80,7 @@ void main()

varnormal = normalize(-varposition);

// Always set clip distance to 1 to disable clipping.
for (int i = 0; i < 6; ++i) {
gl_ClipDistance[i] = 1.0;
}
7 changes: 6 additions & 1 deletion source/blender/makesdna/DNA_texture_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ typedef struct EnvMap {
int ok, lastframe;
short recalc, lastsize;
int flag, filtering;
float lodfactor, pad;
int mode;
float lodfactor;
} EnvMap;

typedef struct PointDensity {
Expand Down Expand Up @@ -481,6 +482,10 @@ typedef struct ColorMapping {
/* flag */
#define ENVMAP_AUTO_UPDATE (1 << 0)

/* mode */
#define ENVMAP_REFLECTION 0
#define ENVMAP_REFRACTION 1

/* filtering */
#define ENVMAP_MIPMAP_NONE 0
#define ENVMAP_MIPMAP_LINEAR 1
Expand Down
11 changes: 11 additions & 0 deletions source/blender/makesrna/intern/rna_texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,12 @@ static void rna_def_environment_map(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};

static EnumPropertyItem prop_mode_items[] = {
{ENVMAP_REFLECTION, "REFLECTION", 0, "Reflection", "Reflection rendering"},
{ENVMAP_REFRACTION, "REFRACTION", 0, "Refraction", "Refraction rendering"},
{0, NULL, 0, NULL, NULL}
};

srna = RNA_def_struct(brna, "EnvironmentMap", NULL);
RNA_def_struct_sdna(srna, "EnvMap");
RNA_def_struct_ui_text(srna, "EnvironmentMap",
Expand Down Expand Up @@ -865,6 +871,11 @@ static void rna_def_environment_map(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", ENVMAP_AUTO_UPDATE);
RNA_def_property_ui_text(prop, "Auto Update", "True if the cube map is updated every frame");

prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, prop_mode_items);
RNA_def_property_ui_text(prop, "Rendering Mode", "Texture rendering method");

prop = RNA_def_property(srna, "lod_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "lodfactor");
RNA_def_property_range(prop, 0.0f, FLT_MAX);
Expand Down
30 changes: 19 additions & 11 deletions source/gameengine/Converter/BL_BlenderDataConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
#include "MT_Transform.h"
#include "MT_MinMax.h"

#include "GPU_texture.h"

#include "PHY_Pro.h"
#include "PHY_IPhysicsEnvironment.h"

Expand Down Expand Up @@ -86,7 +88,8 @@
#include "RAS_BoundingBoxManager.h"
#include "RAS_IPolygonMaterial.h"
#include "KX_BlenderMaterial.h"
#include "KX_CubeMapManager.h"
#include "KX_TextureRendererManager.h"
#include "KX_PlanarMap.h"
#include "KX_CubeMap.h"
#include "BL_Texture.h"

Expand Down Expand Up @@ -1846,20 +1849,25 @@ void BL_ConvertBlenderObjects(struct Main* maggie,

for (unsigned short k = 0; k < RAS_Texture::MaxUnits; ++k) {
RAS_Texture *tex = polymat->GetTexture(k);
if (!tex || !tex->Ok()) {
continue;
}

if (tex && tex->Ok() && tex->IsCubeMap() && tex->GetTex()->env->stype == ENV_REALT) {
EnvMap *env = tex->GetTex()->env;
KX_GameObject *viewpoint = gameobj;
EnvMap *env = tex->GetTex()->env;
if (!env || env->stype != ENV_REALT) {
continue;
}

if (env->object) {
KX_GameObject *obj = converter->FindGameObject(env->object);
if (obj) {
viewpoint = obj;
}
KX_GameObject *viewpoint = gameobj;
if (env->object) {
KX_GameObject *obj = converter->FindGameObject(env->object);
if (obj) {
viewpoint = obj;
}

kxscene->GetCubeMapManager()->AddCubeMap(tex, viewpoint);
}

KX_TextureRendererManager::RendererType type = tex->IsCubeMap() ? KX_TextureRendererManager::CUBE : KX_TextureRendererManager::PLANAR;
kxscene->GetTextureRendererManager()->AddRenderer(type, tex, viewpoint);
}
}
}
Expand Down
16 changes: 9 additions & 7 deletions source/gameengine/Ketsji/BL_Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/

#include "BL_Texture.h"
#include "KX_CubeMap.h"
#include "KX_TextureRenderer.h"

#include "DNA_texture_types.h"

Expand All @@ -42,7 +42,9 @@ BL_Texture::BL_Texture(MTex *mtex)
{
Tex *tex = m_mtex->tex;
EnvMap *env = tex->env;
m_isCubeMap = (env && tex->type == TEX_ENVMAP && (env->stype == ENV_LOAD || env->stype == ENV_REALT));
m_isCubeMap = (env && tex->type == TEX_ENVMAP &&
(env->stype == ENV_LOAD ||
(env->stype == ENV_REALT && env->type == ENV_CUBE)));

Image *ima = tex->ima;
ImageUser& iuser = tex->iuser;
Expand Down Expand Up @@ -249,7 +251,7 @@ PyAttributeDef BL_Texture::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("parallaxStep", BL_Texture, pyattr_get_parallax_step, pyattr_set_parallax_step),
KX_PYATTRIBUTE_RW_FUNCTION("lodBias", BL_Texture, pyattr_get_lod_bias, pyattr_set_lod_bias),
KX_PYATTRIBUTE_RW_FUNCTION("bindCode", BL_Texture, pyattr_get_bind_code, pyattr_set_bind_code),
KX_PYATTRIBUTE_RO_FUNCTION("cubeMap", BL_Texture, pyattr_get_cube_map),
KX_PYATTRIBUTE_RO_FUNCTION("renderer", BL_Texture, pyattr_get_renderer),
KX_PYATTRIBUTE_RW_FUNCTION("ior", BL_Texture, pyattr_get_ior, pyattr_set_ior),
KX_PYATTRIBUTE_RW_FUNCTION("refractionRatio", BL_Texture, pyattr_get_refraction_ratio, pyattr_set_refraction_ratio),
KX_PYATTRIBUTE_RW_FUNCTION("uvRotation", BL_Texture, pyattr_get_uv_rotation, pyattr_set_uv_rotation),
Expand Down Expand Up @@ -519,12 +521,12 @@ int BL_Texture::pyattr_set_bind_code(PyObjectPlus *self_v, const KX_PYATTRIBUTE_
return PY_SET_ATTR_SUCCESS;
}

PyObject *BL_Texture::pyattr_get_cube_map(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
PyObject *BL_Texture::pyattr_get_renderer(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
BL_Texture *self = static_cast<BL_Texture *>(self_v);
KX_CubeMap *cubeMap = (KX_CubeMap *)self->GetCubeMap();
if (cubeMap) {
return cubeMap->GetProxy();
KX_TextureRenderer *renderer = static_cast<KX_TextureRenderer *>(self->GetRenderer());
if (renderer) {
return renderer->GetProxy();
}

Py_RETURN_NONE;
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/Ketsji/BL_Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class BL_Texture : public CValue, public RAS_Texture
static int pyattr_set_lod_bias(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_bind_code(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_bind_code(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_cube_map(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_renderer(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_ior(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_ior(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject *pyattr_get_refraction_ratio(PyObjectPlus *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
Expand Down
12 changes: 8 additions & 4 deletions source/gameengine/Ketsji/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ set(SRC
KX_CameraActuator.cpp
KX_CameraIpoSGController.cpp
KX_CharacterWrapper.cpp
KX_CollisionEventManager.cpp
KX_CollisionSensor.cpp
KX_ConstraintActuator.cpp
KX_ConstraintWrapper.cpp
KX_CubeMap.cpp
KX_CubeMapManager.cpp
KX_EmptyObject.cpp
KX_FontObject.cpp
KX_GameActuator.cpp
Expand All @@ -111,6 +112,7 @@ set(SRC
KX_ObstacleSimulation.cpp
KX_OrientationInterpolator.cpp
KX_ParentActuator.cpp
KX_PlanarMap.cpp
KX_PolyProxy.cpp
KX_PositionInterpolator.cpp
KX_PyConstraintBinding.cpp
Expand All @@ -136,10 +138,10 @@ set(SRC
KX_StateActuator.cpp
KX_SteeringActuator.cpp
KX_TextMaterial.cpp
KX_TextureRenderer.cpp
KX_TextureRendererManager.cpp
KX_TimeCategoryLogger.cpp
KX_TimeLogger.cpp
KX_CollisionEventManager.cpp
KX_CollisionSensor.cpp
KX_TrackToActuator.cpp
KX_VehicleWrapper.cpp
KX_VertexProxy.cpp
Expand Down Expand Up @@ -168,7 +170,6 @@ set(SRC
KX_ConstraintActuator.h
KX_ConstraintWrapper.h
KX_CubeMap.h
KX_CubeMapManager.h
KX_EmptyObject.h
KX_FontObject.h
KX_GameActuator.h
Expand Down Expand Up @@ -200,6 +201,7 @@ set(SRC
KX_OrientationInterpolator.h
KX_ParentActuator.h
KX_PhysicsEngineEnums.h
KX_PlanarMap.h
KX_PolyProxy.h
KX_PositionInterpolator.h
KX_PyConstraintBinding.h
Expand All @@ -225,6 +227,8 @@ set(SRC
KX_StateActuator.h
KX_SteeringActuator.h
KX_TextMaterial.h
KX_TextureRenderer.h
KX_TextureRendererManager.h
KX_TimeCategoryLogger.h
KX_TimeLogger.h
KX_CollisionEventManager.h
Expand Down
Loading

0 comments on commit acdbcc2

Please sign in to comment.