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

Add spotlight to default shader #3069

Closed
wants to merge 2 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
68 changes: 62 additions & 6 deletions gdx/src/com/badlogic/gdx/graphics/g3d/shaders/DefaultShader.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*******************************************************************************
* 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.
Expand Down Expand Up @@ -34,10 +34,12 @@
import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.PointLightsAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.SpotLightsAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.graphics.g3d.environment.AmbientCubemap;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.environment.PointLight;
import com.badlogic.gdx.graphics.g3d.environment.SpotLight;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Matrix3;
Expand All @@ -57,7 +59,7 @@ public static class Config {
/** The number of point lights to use */
public int numPointLights = 5;
/** The number of spot lights to use */
public int numSpotLights = 0;
public int numSpotLights = 5;
/** The number of bones to use */
public int numBones = 12;
/** */
Expand Down Expand Up @@ -113,6 +115,7 @@ public static class Inputs {
public final static Uniform ambientCube = new Uniform("u_ambientCubemap");
public final static Uniform dirLights = new Uniform("u_dirLights");
public final static Uniform pointLights = new Uniform("u_pointLights");
public final static Uniform spotLights = new Uniform("u_spotLights");
public final static Uniform environmentCubemap = new Uniform("u_environmentCubemap");
}

Expand Down Expand Up @@ -444,6 +447,12 @@ public static String getDefaultFragmentShader () {
protected final int u_pointLights0position = register(new Uniform("u_pointLights[0].position"));
protected final int u_pointLights0intensity = register(new Uniform("u_pointLights[0].intensity"));
protected final int u_pointLights1color = register(new Uniform("u_pointLights[1].color"));
protected final int u_spotLights0color = register(new Uniform("u_spotLights[0].color"));
protected final int u_spotLights0position = register(new Uniform("u_spotLights[0].position"));
protected final int u_spotLights0intensity = register(new Uniform("u_spotLights[0].intensity"));
protected final int u_spotLights0direction = register(new Uniform("u_spotLights[0].direction"));
protected final int u_spotLights0cutoffAngle = register(new Uniform("u_spotLights[0].cutoffAngle"));
protected final int u_spotLights1color = register(new Uniform("u_spotLights[1].color"));
protected final int u_fogColor = register(new Uniform("u_fogColor"));
protected final int u_shadowMapProjViewTrans = register(new Uniform("u_shadowMapProjViewTrans"));
protected final int u_shadowTexture = register(new Uniform("u_shadowTexture"));
Expand All @@ -459,13 +468,21 @@ public static String getDefaultFragmentShader () {
protected int pointLightsPositionOffset;
protected int pointLightsIntensityOffset;
protected int pointLightsSize;
protected int spotLightsLoc;
protected int spotLightsColorOffset;
protected int spotLightsPositionOffset;
protected int spotLightsDirectionOffset;
protected int spotLightsIntensityOffset;
protected int spotLightsCutoffAngleOffset;
protected int spotLightsSize;

protected final boolean lighting;
protected final boolean environmentCubemap;
protected final boolean shadowMap;
protected final AmbientCubemap ambientCubemap = new AmbientCubemap();
protected final DirectionalLight directionalLights[];
protected final PointLight pointLights[];
protected final SpotLight spotLights[];

/** The renderable used to create this shader, invalid after the call to init */
private Renderable renderable;
Expand Down Expand Up @@ -512,6 +529,9 @@ public DefaultShader (final Renderable renderable, final Config config, final Sh
this.pointLights = new PointLight[lighting && config.numPointLights > 0 ? config.numPointLights : 0];
for (int i = 0; i < pointLights.length; i++)
pointLights[i] = new PointLight();
this.spotLights = new SpotLight[lighting && config.numSpotLights > 0 ? config.numSpotLights : 0];
for (int i = 0; i < spotLights.length; i++)
spotLights[i] = new SpotLight();

if (!config.ignoreUnimplemented && (implementedFlags & attributesMask) != attributesMask)
throw new GdxRuntimeException("Some attributes not implemented yet (" + attributesMask + ")");
Expand Down Expand Up @@ -576,6 +596,15 @@ public void init () {
pointLightsIntensityOffset = has(u_pointLights0intensity) ? loc(u_pointLights0intensity) - pointLightsLoc : -1;
pointLightsSize = loc(u_pointLights1color) - pointLightsLoc;
if (pointLightsSize < 0) pointLightsSize = 0;

spotLightsLoc = loc(u_spotLights0color);
spotLightsColorOffset = loc(u_spotLights0color) - spotLightsLoc;
spotLightsPositionOffset = loc(u_spotLights0position) - spotLightsLoc;
spotLightsDirectionOffset = loc(u_spotLights0direction) - spotLightsLoc;
spotLightsIntensityOffset = has(u_spotLights0intensity) ? loc(u_spotLights0intensity) - spotLightsLoc : -1;
spotLightsCutoffAngleOffset = loc(u_spotLights0cutoffAngle) - spotLightsLoc;
spotLightsSize = loc(u_spotLights1color) - spotLightsLoc;
if (spotLightsSize < 0) spotLightsSize = 0;
}

private static final boolean and (final long mask, final long flag) {
Expand Down Expand Up @@ -612,6 +641,7 @@ public static String createPrefix (final Renderable renderable, final Config con
prefix += "#define ambientCubemapFlag\n";
prefix += "#define numDirectionalLights " + config.numDirectionalLights + "\n";
prefix += "#define numPointLights " + config.numPointLights + "\n";
prefix += "#define numSpotLights " + config.numSpotLights + "\n";
if (attributes.has(ColorAttribute.Fog)) {
prefix += "#define fogFlag\n";
}
Expand Down Expand Up @@ -704,6 +734,8 @@ public void begin (final Camera camera, final RenderContext context) {
dirLight.set(0, 0, 0, 0, -1, 0);
for (final PointLight pointLight : pointLights)
pointLight.set(0, 0, 0, 0, 0, 0, 0);
for (final SpotLight spotLight : spotLights)
spotLight.set(0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1);
lightsSet = false;

if (has(u_time)) set(u_time, time += Gdx.graphics.getDeltaTime());
Expand Down Expand Up @@ -756,11 +788,13 @@ else if ((t & DepthTestAttribute.Type) == DepthTestAttribute.Type) {
private final Vector3 tmpV1 = new Vector3();

protected void bindLights (final Renderable renderable, final Attributes attributes) {
final Environment lights = renderable.environment;
final Environment lights = renderable.environment;
final DirectionalLightsAttribute dla = attributes.get(DirectionalLightsAttribute.class, DirectionalLightsAttribute.Type);
final Array<DirectionalLight> dirs = dla == null ? null : dla.lights;
final PointLightsAttribute pla = attributes.get(PointLightsAttribute.class, PointLightsAttribute.Type);
final Array<PointLight> points = pla == null ? null : pla.lights;
final SpotLightsAttribute sla = attributes.get(SpotLightsAttribute.class, SpotLightsAttribute.Type);
final Array<SpotLight> spots = sla == null ? null : sla.lights;

if (dirLightsLoc >= 0) {
for (int i = 0; i < directionalLights.length; i++) {
Expand Down Expand Up @@ -802,14 +836,36 @@ protected void bindLights (final Renderable renderable, final Attributes attribu
}
}

if (spotLightsLoc >= 0) {
for (int i = 0; i < spotLights.length; i++) {
if (spots == null || i >= spots.size) {
if (lightsSet && spotLights[i].intensity == 0f) continue;
spotLights[i].intensity = 0f;
} else if (lightsSet && spotLights[i].equals(spots.get(i)))
continue;
else
spotLights[i].set(spots.get(i));

int idx = spotLightsLoc + i * spotLightsSize;
program.setUniformf(idx + spotLightsColorOffset, spotLights[i].color.r * spotLights[i].intensity,
spotLights[i].color.g * spotLights[i].intensity, spotLights[i].color.b * spotLights[i].intensity);
program.setUniformf(idx + spotLightsPositionOffset, spotLights[i].position);
program.setUniformf(idx + spotLightsDirectionOffset, spotLights[i].direction);
program.setUniformf(idx + spotLightsCutoffAngleOffset, spotLights[i].cutoffAngle);
if (spotLightsIntensityOffset >= 0)
program.setUniformf(idx + spotLightsIntensityOffset, spotLights[i].intensity);
if (spotLightsSize <= 0) break;
}
}

if (attributes.has(ColorAttribute.Fog)) {
set(u_fogColor, ((ColorAttribute)attributes.get(ColorAttribute.Fog)).color);
}

if (lights.shadowMap != null) {
set(u_shadowMapProjViewTrans, lights.shadowMap.getProjViewTrans());
set(u_shadowTexture, lights.shadowMap.getDepthMap());
set(u_shadowPCFOffset, 1.f / (float)(2f * lights.shadowMap.getDepthMap().texture.getWidth()));
set(u_shadowPCFOffset, 1.f / (2f * lights.shadowMap.getDepthMap().texture.getWidth()));
}

lightsSet = true;
Expand Down
30 changes: 30 additions & 0 deletions gdx/src/com/badlogic/gdx/graphics/g3d/shaders/default.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@ struct PointLight
uniform PointLight u_pointLights[numPointLights];
#endif // numPointLights

#if defined(numSpotLights) && (numSpotLights > 0)
struct SpotLight
{
vec3 color;
vec3 position;
vec3 direction;
float cutoffAngle;
};
uniform SpotLight u_spotLights[numSpotLights];
#endif // numSpotLights

#if defined(ambientLightFlag) || defined(ambientCubemapFlag) || defined(sphericalHarmonicsFlag)
#define ambientFlag
#endif //ambientFlag
Expand Down Expand Up @@ -332,5 +343,24 @@ void main() {
#endif // specularFlag
}
#endif // numPointLights

#if defined(numSpotLights) && (numSpotLights > 0) && defined(normalFlag)
for (int i = 0; i < numSpotLights; i++) {
vec3 lightDir = u_spotLights[i].position - pos.xyz;
float spotEffect = dot(-normalize(lightDir), normalize(u_spotLights[i].direction));

if ( spotEffect > u_spotLights[i].cutoffAngle ) {
float dist2 = dot(lightDir, lightDir);
lightDir *= inversesqrt(dist2);
float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0);
vec3 value = u_spotLights[i].color * (NdotL / (1.0 + dist2));
v_lightDiffuse += value;
#ifdef specularFlag
float halfDotView = max(0.0, dot(normal, normalize(lightDir + viewVec)));
v_lightSpecular += value * pow(halfDotView, u_shininess);
#endif // specularFlag
}
}
#endif // numSpotLights
#endif // lightingFlag
}
10 changes: 10 additions & 0 deletions tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/LightsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.environment.PointLight;
import com.badlogic.gdx.graphics.g3d.environment.SpotLight;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;

public class LightsTest extends ModelTest {
DirectionalLight dirLight;
PointLight pointLight;
SpotLight spotLight;
Model lightModel;
Renderable pLight;
Vector3 center = new Vector3(), transformedCenter = new Vector3(), tmpV = new Vector3();
Expand All @@ -46,6 +49,7 @@ public void create () {
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.2f, 0.2f, 0.2f, 1.0f));
environment.add(dirLight = new DirectionalLight().set(0.8f, 0.2f, 0.2f, -1f, -2f, -0.5f));
environment.add(pointLight = new PointLight().set(0.2f, 0.8f, 0.2f, 0f, 0f, 0f, 100f));
environment.add(spotLight = new SpotLight().set(0.2f, 0.2f, 0.8f, 0f, 0f, 0f, -1f, -2f, -0.5f, 100f, (float)Math.cos(Math.toRadians(45))));

ModelBuilder mb = new ModelBuilder();
lightModel = mb.createSphere(1, 1, 1, 10, 10, new Material(ColorAttribute.createDiffuse(1, 1, 1, 1)), Usage.Position);
Expand All @@ -63,6 +67,10 @@ protected void onLoaded () {
((ColorAttribute)pLight.material.get(ColorAttribute.Diffuse)).color.set(pointLight.color);
final float s = 0.2f * radius;
pLight.worldTransform.setToScaling(s, s, s);

spotLight.position.set(0, radius, 0).add(transformedCenter.set(center).mul(transform));
spotLight.intensity = radius * radius;
spotLight.direction.set(center.cpy().sub(spotLight.position).nor());
}

@Override
Expand All @@ -78,6 +86,8 @@ protected void render (ModelBatch batch, Array<ModelInstance> instances) {
pointLight.position.rotate(Vector3.Z, delta * 3f);
pointLight.position.add(transformedCenter.set(center).mul(transform));

spotLight.cutoffAngle = (float)Math.cos(Math.toRadians((TimeUtils.millis()/100)%45));

pLight.worldTransform.setTranslation(pointLight.position);
batch.render(pLight);

Expand Down