Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shadow cube for point light #5018

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions gdx/src/com/badlogic/gdx.gwt.xml
Expand Up @@ -161,6 +161,7 @@
<include name="graphics/g3d/environment/DirectionalLight.java"/>
<include name="graphics/g3d/environment/DirectionalShadowLight.java"/>
<include name="graphics/g3d/environment/PointLight.java"/>
<include name="graphics/g3d/environment/PointShadowLight.java"/>
<include name="graphics/g3d/environment/SpotLight.java"/>
<include name="graphics/g3d/environment/ShadowMap.java"/>
<include name="graphics/g3d/environment/Sphericalharmonics.java"/>
Expand Down
2 changes: 2 additions & 0 deletions gdx/src/com/badlogic/gdx/graphics/g3d/Environment.java
Expand Up @@ -22,6 +22,7 @@
import com.badlogic.gdx.graphics.g3d.environment.BaseLight;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.environment.PointLight;
import com.badlogic.gdx.graphics.g3d.environment.PointShadowLight;
import com.badlogic.gdx.graphics.g3d.environment.ShadowMap;
import com.badlogic.gdx.graphics.g3d.environment.SpotLight;
import com.badlogic.gdx.utils.Array;
Expand All @@ -30,6 +31,7 @@
public class Environment extends Attributes {
/** @deprecated Experimental, likely to change, do not use! */
public ShadowMap shadowMap;
public PointShadowLight shadowBox;

public Environment () {
}
Expand Down
@@ -0,0 +1,120 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/

package com.badlogic.gdx.graphics.g3d.environment;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.utils.DepthShaderProvider;
import com.badlogic.gdx.graphics.g3d.utils.TextureDescriptor;
import com.badlogic.gdx.graphics.glutils.FrameBufferCubemap;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.GdxRuntimeException;



/** Creates a shadow cubemap for a PointLight by rendering the depth information for the objects in a scene in each of
* 6 directions from the light.
*
* An example usage is
* Environment environment = new Environment();
* PointShadowLight shadowLight = new PointShadowLight(1024, 1024, 30f, 30f, 1f, 100f);
* shadowLight.set(...);
* environment.add(shadowLight);
* environment.shadowBox = shadowLight;
* ModelBatch modelBatch = new ModelBatch();
* ModelBatch shadowModelBatch(new DepthShaderProvider());
* ModelInstance instance = ...
* shadowLight.begin();
* while (shadowLight.nextSide()) {
* shadowModelBatch.begin(shadowLight.camera);
* shadowModelBatch.render(instance);
* shadowModelBatch.end();
* }
* shadowLight.end();
*
* modelBatch.begin(cam);
* modelBatch.render(instance, environment);
* modelBatch.end();
*
* @deprecated Experimental, likely to change, do not use!
* @author ryanastout */
public class PointShadowLight extends PointLight implements Disposable {
protected FrameBufferCubemap frameBufferCube;
public Camera camera;
protected TextureDescriptor textureDesc;
private boolean beginCalled;

public PointShadowLight (int shadowMapWidth, int shadowMapHeight, float shadowViewportWidth, float shadowViewportHeight,
float shadowNear, float shadowFar) {
camera = new PerspectiveCamera(90, shadowViewportWidth, shadowViewportHeight);
camera.near = shadowNear;
camera.far = shadowFar;

textureDesc = new TextureDescriptor();
textureDesc.minFilter = textureDesc.magFilter = Texture.TextureFilter.Nearest;
textureDesc.uWrap = textureDesc.vWrap = Texture.TextureWrap.ClampToEdge;
beginCalled = false;
frameBufferCube = new FrameBufferCubemap(Pixmap.Format.RGB888, shadowMapWidth, shadowMapHeight, true);
}

public void begin () {
final int w = frameBufferCube.getWidth();
final int h = frameBufferCube.getHeight();
frameBufferCube.begin();
Gdx.gl.glViewport(0, 0, w, h);
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
camera.position.set(position);
beginCalled = true;
}

public void end () {
beginCalled = false;
frameBufferCube.end();
}

public FrameBufferCubemap getFrameBufferCube () {
return frameBufferCube;
}

@Override
public void dispose () {
if (frameBufferCube != null) frameBufferCube.dispose();
frameBufferCube = null;
}

public boolean nextSide () {
if (!beginCalled) {
throw new GdxRuntimeException("call begin() before calling nextSide()");
}

if (!frameBufferCube.nextSide()) {
return false;
}
frameBufferCube.getSide().getUp(camera.up);
frameBufferCube.getSide().getDirection(camera.direction);
camera.update();

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
return true;
}
}
19 changes: 15 additions & 4 deletions gdx/src/com/badlogic/gdx/graphics/g3d/shaders/DefaultShader.java
Expand Up @@ -466,6 +466,9 @@ public static String getDefaultFragmentShader () {
protected final int u_shadowMapProjViewTrans = register(new Uniform("u_shadowMapProjViewTrans"));
protected final int u_shadowTexture = register(new Uniform("u_shadowTexture"));
protected final int u_shadowPCFOffset = register(new Uniform("u_shadowPCFOffset"));
protected final int u_lightPosition = register(new Uniform("u_lightPosition"));
protected final int u_shadowBoxNearFar = register(new Uniform("u_shadowBoxNearFar"));
protected final int u_shadowBox = register(new Uniform("u_shadowBox"));
// FIXME Cache vertex attribute locations...

protected int dirLightsLoc;
Expand Down Expand Up @@ -665,6 +668,7 @@ public static String createPrefix (final Renderable renderable, final Config con
prefix += "#define fogFlag\n";
}
if (renderable.environment.shadowMap != null) prefix += "#define shadowMapFlag\n";
if (renderable.environment.shadowBox != null) prefix += "#define shadowBoxFlag\n";
if (attributes.has(CubemapAttribute.EnvironmentMap)) prefix += "#define environmentCubemapFlag\n";
}
}
Expand Down Expand Up @@ -881,10 +885,17 @@ protected void bindLights (final Renderable renderable, final Attributes attribu
set(u_fogColor, ((ColorAttribute)attributes.get(ColorAttribute.Fog)).color);
}

if (lights != null && lights.shadowMap != null) {
set(u_shadowMapProjViewTrans, lights.shadowMap.getProjViewTrans());
set(u_shadowTexture, lights.shadowMap.getDepthMap());
set(u_shadowPCFOffset, 1.f / (2f * lights.shadowMap.getDepthMap().texture.getWidth()));
if (lights != null) {
if (lights.shadowMap != null) {
set(u_shadowMapProjViewTrans, lights.shadowMap.getProjViewTrans());
set(u_shadowTexture, lights.shadowMap.getDepthMap());
set(u_shadowPCFOffset, 1.f / (2f * lights.shadowMap.getDepthMap().texture.getWidth()));
}
if (lights.shadowBox != null) {
set(u_lightPosition, lights.shadowBox.position);
set(u_shadowBoxNearFar, lights.shadowBox.camera.near, lights.shadowBox.camera.far);
set(u_shadowBox, lights.shadowBox.getFrameBufferCube().getColorBufferTexture());
}
}

lightsSet = true;
Expand Down
Expand Up @@ -93,6 +93,30 @@ float getShadow()
}
#endif //shadowMapFlag

#if defined(shadowBoxFlag) && !defined(shadowMapFlag)
#define separateAmbientFlag

uniform samplerCube u_shadowBox;
uniform vec2 u_shadowBoxNearFar;

varying vec3 v_lightToPos;

float convertToDepth(float z) {
return (z - u_shadowBoxNearFar.x) / (u_shadowBoxNearFar.y - u_shadowBoxNearFar.x);
}

float maxAbs(vec3 v) {
return max(max(abs(v.x), abs(v.y)), abs(v.z));
}

float getShadow() {
const vec4 bitShifts = vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0);
HIGH float extracted = dot(textureCube(u_shadowBox, v_lightToPos), bitShifts);
HIGH float fragDepth = convertToDepth(maxAbs(v_lightToPos));
return step(fragDepth, extracted);
}
#endif //shadowBoxFlag

#if defined(ambientFlag) && defined(separateAmbientFlag)
varying vec3 v_ambientLight;
#endif //separateAmbientFlag
Expand Down Expand Up @@ -131,14 +155,13 @@ void main() {
gl_FragColor.rgb = diffuse.rgb;
#elif (!defined(specularFlag))
#if defined(ambientFlag) && defined(separateAmbientFlag)
#ifdef shadowMapFlag
#if defined(shadowMapFlag) || defined(shadowBoxFlag)
gl_FragColor.rgb = (diffuse.rgb * (v_ambientLight + getShadow() * v_lightDiffuse));
//gl_FragColor.rgb = texture2D(u_shadowTexture, v_shadowMapUv.xy);
#else
gl_FragColor.rgb = (diffuse.rgb * (v_ambientLight + v_lightDiffuse));
#endif //shadowMapFlag
#else
#ifdef shadowMapFlag
#if defined(shadowMapFlag) || defined(shadowBoxFlag)
gl_FragColor.rgb = getShadow() * (diffuse.rgb * v_lightDiffuse);
#else
gl_FragColor.rgb = (diffuse.rgb * v_lightDiffuse);
Expand All @@ -156,14 +179,13 @@ void main() {
#endif

#if defined(ambientFlag) && defined(separateAmbientFlag)
#ifdef shadowMapFlag
gl_FragColor.rgb = (diffuse.rgb * (getShadow() * v_lightDiffuse + v_ambientLight)) + specular;
//gl_FragColor.rgb = texture2D(u_shadowTexture, v_shadowMapUv.xy);
#if defined(shadowMapFlag) || defined(shadowBoxFlag)
gl_FragColor.rgb = (diffuse.rgb * (getShadow() * v_lightDiffuse + v_ambientLight)) + specular;
#else
gl_FragColor.rgb = (diffuse.rgb * (v_lightDiffuse + v_ambientLight)) + specular;
#endif //shadowMapFlag
#else
#ifdef shadowMapFlag
#if defined(shadowMapFlag) || defined(shadowBoxFlag)
gl_FragColor.rgb = getShadow() * ((diffuse.rgb * v_lightDiffuse) + specular);
#else
gl_FragColor.rgb = (diffuse.rgb * v_lightDiffuse) + specular;
Expand All @@ -184,5 +206,4 @@ void main() {
#else
gl_FragColor.a = 1.0;
#endif

}
10 changes: 10 additions & 0 deletions gdx/src/com/badlogic/gdx/graphics/g3d/shaders/default.vertex.glsl
Expand Up @@ -178,6 +178,12 @@ varying vec3 v_shadowMapUv;
#define separateAmbientFlag
#endif //shadowMapFlag

#if defined(shadowBoxFlag) && !defined(shadowMapFlag)
varying vec3 v_lightToPos;
uniform vec3 u_lightPosition;
#define separateAmbientFlag
#endif //shadowBoxFlag

#if defined(ambientFlag) && defined(separateAmbientFlag)
varying vec3 v_ambientLight;
#endif //separateAmbientFlag
Expand Down Expand Up @@ -246,6 +252,10 @@ void main() {
v_shadowMapUv.z = min(v_shadowMapUv.z, 0.998);
#endif //shadowMapFlag

#ifdef shadowBoxFlag
v_lightToPos = pos.xyz - u_lightPosition;
#endif //shadowBoxFlag

#if defined(normalFlag)
#if defined(skinningFlag)
vec3 normal = normalize((u_worldTrans * skinning * vec4(a_normal, 0.0)).xyz);
Expand Down
18 changes: 12 additions & 6 deletions gdx/src/com/badlogic/gdx/graphics/g3d/shaders/depth.vertex.glsl
@@ -1,5 +1,7 @@
attribute vec3 a_position;
uniform mat4 u_projViewWorldTrans;
uniform mat4 u_viewWorldTrans;
uniform mat4 u_projTrans;
uniform vec2 u_cameraNearFar;

#if defined(diffuseTextureFlag) && defined(blendedFlag)
#define blendedTextureFlag
Expand Down Expand Up @@ -111,15 +113,19 @@ void main() {
#endif //boneWeight7Flag
#endif //skinningFlag



#ifdef skinningFlag
vec4 pos = u_projViewWorldTrans * skinning * vec4(a_position, 1.0);
vec4 viewPos = u_viewWorldTrans * skinning * vec4(a_position, 1.0);
#else
vec4 pos = u_projViewWorldTrans * vec4(a_position, 1.0);
vec4 viewPos = u_viewWorldTrans * vec4(a_position, 1.0);
#endif


vec4 pos = u_projTrans * viewPos;

#ifdef PackedDepthFlag
v_depth = pos.z / pos.w * 0.5 + 0.5;
v_depth = (-viewPos.z - u_cameraNearFar.x) / (u_cameraNearFar.y - u_cameraNearFar.x);
#endif //PackedDepthFlag

gl_Position = pos;
}