- Added SpotLight light type.
- Implemented spot light shading for lighting (pixel and vertex lighting) and terrain shader git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7893 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
41f417570d
commit
99a4b00c15
@ -52,8 +52,9 @@ uniform float m_Shininess;
|
|||||||
|
|
||||||
#ifdef HQ_ATTENUATION
|
#ifdef HQ_ATTENUATION
|
||||||
uniform vec4 g_LightPosition;
|
uniform vec4 g_LightPosition;
|
||||||
varying vec3 lightVec;
|
|
||||||
#endif
|
#endif
|
||||||
|
varying vec4 lightVec;
|
||||||
|
varying vec4 spotVec;
|
||||||
|
|
||||||
#ifdef USE_REFLECTION
|
#ifdef USE_REFLECTION
|
||||||
uniform float m_ReflectionPower;
|
uniform float m_ReflectionPower;
|
||||||
@ -146,6 +147,23 @@ void main(){
|
|||||||
#else
|
#else
|
||||||
vec4 diffuseColor = vec4(1.0);
|
vec4 diffuseColor = vec4(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef VERTEX_LIGHTING
|
||||||
|
float spotFallOff = 1.0;
|
||||||
|
if(spotVec.w!=0){
|
||||||
|
vec3 L=normalize(lightVec.xyz);
|
||||||
|
vec3 spotdir = normalize(spotVec.xyz);
|
||||||
|
float curAngleCos = dot(-L, spotdir);
|
||||||
|
float innerAngleCos = spotVec.w;
|
||||||
|
float outerAngleCos = lightVec.w;
|
||||||
|
float innerMinusOuter = innerAngleCos - outerAngleCos;
|
||||||
|
spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
|
||||||
|
if(spotFallOff<=0.0){
|
||||||
|
gl_FragColor = AmbientSum * diffuseColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
float alpha = DiffuseSum.a * diffuseColor.a;
|
float alpha = DiffuseSum.a * diffuseColor.a;
|
||||||
#ifdef ALPHAMAP
|
#ifdef ALPHAMAP
|
||||||
alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;
|
alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;
|
||||||
@ -202,7 +220,7 @@ void main(){
|
|||||||
vec4 lightDir = vLightDir;
|
vec4 lightDir = vLightDir;
|
||||||
lightDir.xyz = normalize(lightDir.xyz);
|
lightDir.xyz = normalize(lightDir.xyz);
|
||||||
|
|
||||||
vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz);
|
vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz) * spotFallOff;
|
||||||
#ifdef COLORRAMP
|
#ifdef COLORRAMP
|
||||||
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
|
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
|
||||||
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
|
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
|
||||||
|
@ -13,6 +13,7 @@ uniform float m_Shininess;
|
|||||||
|
|
||||||
uniform vec4 g_LightColor;
|
uniform vec4 g_LightColor;
|
||||||
uniform vec4 g_LightPosition;
|
uniform vec4 g_LightPosition;
|
||||||
|
uniform vec4 g_LightDirection;
|
||||||
uniform vec4 g_AmbientLightColor;
|
uniform vec4 g_AmbientLightColor;
|
||||||
|
|
||||||
varying vec2 texCoord;
|
varying vec2 texCoord;
|
||||||
@ -29,9 +30,8 @@ attribute vec3 inPosition;
|
|||||||
attribute vec2 inTexCoord;
|
attribute vec2 inTexCoord;
|
||||||
attribute vec3 inNormal;
|
attribute vec3 inNormal;
|
||||||
|
|
||||||
#ifdef HQ_ATTENUATION
|
varying vec4 lightVec;
|
||||||
varying vec3 lightVec;
|
varying vec4 spotVec;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VERTEX_COLOR
|
#ifdef VERTEX_COLOR
|
||||||
attribute vec4 inColor;
|
attribute vec4 inColor;
|
||||||
@ -81,13 +81,11 @@ attribute vec3 inNormal;
|
|||||||
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
|
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
|
||||||
float posLight = step(0.5, color.w);
|
float posLight = step(0.5, color.w);
|
||||||
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
|
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
|
||||||
|
lightVec.xyz = tempVec;
|
||||||
#ifdef ATTENUATION
|
#ifdef ATTENUATION
|
||||||
float dist = length(tempVec);
|
float dist = length(tempVec);
|
||||||
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
|
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
|
||||||
lightDir.xyz = tempVec / vec3(dist);
|
lightDir.xyz = tempVec / vec3(dist);
|
||||||
#ifdef HQ_ATTENUATION
|
|
||||||
lightVec = tempVec;
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
lightDir = vec4(normalize(tempVec), 1.0);
|
lightDir = vec4(normalize(tempVec), 1.0);
|
||||||
#endif
|
#endif
|
||||||
@ -113,11 +111,20 @@ void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4
|
|||||||
vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightPos){
|
vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightPos){
|
||||||
vec4 lightDir;
|
vec4 lightDir;
|
||||||
lightComputeDir(wvPos, g_LightColor, wvLightPos, lightDir);
|
lightComputeDir(wvPos, g_LightColor, wvLightPos, lightDir);
|
||||||
|
float spotFallOff = 1.0;
|
||||||
|
if(spotVec.w!=0){
|
||||||
|
vec3 L=normalize(lightVec.xyz);
|
||||||
|
vec3 spotdir = normalize(spotVec.xyz);
|
||||||
|
float curAngleCos = dot(-L, spotdir);
|
||||||
|
float innerAngleCos = spotVec.w;
|
||||||
|
float outerAngleCos = lightVec.w;
|
||||||
|
float innerMinusOuter = innerAngleCos - outerAngleCos;
|
||||||
|
spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
|
||||||
|
}
|
||||||
float diffuseFactor = lightComputeDiffuse(wvNorm, lightDir.xyz);
|
float diffuseFactor = lightComputeDiffuse(wvNorm, lightDir.xyz);
|
||||||
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, lightDir.xyz, m_Shininess);
|
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, lightDir.xyz, m_Shininess);
|
||||||
//specularFactor *= step(0.01, diffuseFactor);
|
//specularFactor *= step(0.01, diffuseFactor);
|
||||||
return vec2(diffuseFactor, specularFactor) * vec2(lightDir.w);
|
return vec2(diffuseFactor, specularFactor) * vec2(lightDir.w)*spotFallOff;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -138,7 +145,7 @@ void main(){
|
|||||||
//vec4 wvLightPos = (g_ViewMatrix * vec4(lightPos.xyz, lightColor.w));
|
//vec4 wvLightPos = (g_ViewMatrix * vec4(lightPos.xyz, lightColor.w));
|
||||||
//wvLightPos.w = lightPos.w;
|
//wvLightPos.w = lightPos.w;
|
||||||
|
|
||||||
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz, g_LightColor.w));
|
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz,clamp(g_LightColor.w,0.0,1.0)));
|
||||||
wvLightPos.w = g_LightPosition.w;
|
wvLightPos.w = g_LightPosition.w;
|
||||||
vec4 lightColor = g_LightColor;
|
vec4 lightColor = g_LightColor;
|
||||||
|
|
||||||
@ -166,6 +173,11 @@ void main(){
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//computing spot direction in view space and unpacking spotlight cos
|
||||||
|
spotVec=(g_ViewMatrix *vec4(g_LightDirection.xyz,0.0) );
|
||||||
|
spotVec.w=floor(g_LightDirection.w)*0.001;
|
||||||
|
lightVec.w = fract(g_LightDirection.w);
|
||||||
|
|
||||||
lightColor.w = 1.0;
|
lightColor.w = 1.0;
|
||||||
#ifdef MATERIAL_COLORS
|
#ifdef MATERIAL_COLORS
|
||||||
AmbientSum = m_Ambient * g_AmbientLightColor;
|
AmbientSum = m_Ambient * g_AmbientLightColor;
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
@ -55,13 +54,14 @@ public class PointLight extends Light {
|
|||||||
|
|
||||||
protected Vector3f position = new Vector3f();
|
protected Vector3f position = new Vector3f();
|
||||||
protected float radius = 0;
|
protected float radius = 0;
|
||||||
|
protected float invRadius = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void computeLastDistance(Spatial owner) {
|
public void computeLastDistance(Spatial owner) {
|
||||||
if (owner.getWorldBound() != null){
|
if (owner.getWorldBound() != null) {
|
||||||
BoundingVolume bv = owner.getWorldBound();
|
BoundingVolume bv = owner.getWorldBound();
|
||||||
lastDistance = bv.distanceSquaredTo(position);
|
lastDistance = bv.distanceSquaredTo(position);
|
||||||
}else{
|
} else {
|
||||||
lastDistance = owner.getWorldTranslation().distanceSquared(position);
|
lastDistance = owner.getWorldTranslation().distanceSquared(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ public class PointLight extends Light {
|
|||||||
*
|
*
|
||||||
* @param position the world space position of the light.
|
* @param position the world space position of the light.
|
||||||
*/
|
*/
|
||||||
public void setPosition(Vector3f position){
|
public void setPosition(Vector3f position) {
|
||||||
this.position.set(position);
|
this.position.set(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ public class PointLight extends Light {
|
|||||||
*
|
*
|
||||||
* @return the radius of the light
|
* @return the radius of the light
|
||||||
*/
|
*/
|
||||||
public float getRadius(){
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,11 +109,24 @@ public class PointLight extends Light {
|
|||||||
*
|
*
|
||||||
* @throws IllegalArgumentException If radius is negative
|
* @throws IllegalArgumentException If radius is negative
|
||||||
*/
|
*/
|
||||||
public void setRadius(float radius){
|
public void setRadius(float radius) {
|
||||||
if (radius < 0) {
|
if (radius < 0) {
|
||||||
throw new IllegalArgumentException("Light radius cannot be negative");
|
throw new IllegalArgumentException("Light radius cannot be negative");
|
||||||
}
|
}
|
||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
|
if(radius!=0){
|
||||||
|
this.invRadius = 1 / radius;
|
||||||
|
}else{
|
||||||
|
this.invRadius = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for internal use only
|
||||||
|
* @return the inverse of the radius
|
||||||
|
*/
|
||||||
|
public float getInvRadius() {
|
||||||
|
return invRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -135,6 +148,10 @@ public class PointLight extends Light {
|
|||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
position = (Vector3f) ic.readSavable("position", null);
|
position = (Vector3f) ic.readSavable("position", null);
|
||||||
radius = ic.readFloat("radius", 0f);
|
radius = ic.readFloat("radius", 0f);
|
||||||
|
if(radius!=0){
|
||||||
|
this.invRadius = 1 / radius;
|
||||||
|
}else{
|
||||||
|
this.invRadius = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
222
engine/src/core/com/jme3/light/SpotLight.java
Normal file
222
engine/src/core/com/jme3/light/SpotLight.java
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.jme3.light;
|
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingVolume;
|
||||||
|
import com.jme3.export.InputCapsule;
|
||||||
|
import com.jme3.export.JmeExporter;
|
||||||
|
import com.jme3.export.JmeImporter;
|
||||||
|
import com.jme3.export.OutputCapsule;
|
||||||
|
import com.jme3.export.Savable;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a spot light.
|
||||||
|
* A spot light emmit a cone of light from a position and in a direction.
|
||||||
|
* It can be used to fake torch lights or car's lights.
|
||||||
|
* <p>
|
||||||
|
* In addition to a position and a direction, spot lights also have a range which
|
||||||
|
* can be used to attenuate the influence of the light depending on the
|
||||||
|
* distance between the light and the effected object.
|
||||||
|
* Also the angle of the cone can be tweaked by changing the spot inner angle and the spot outer angle.
|
||||||
|
* the spot inner angle determin the cone of light where light has full influence.
|
||||||
|
* the spot outer angle determin the cone global cone of light of the spot light.
|
||||||
|
* the light intensity slowly decrease between the inner cone and the outer cone.
|
||||||
|
* @author Nehon
|
||||||
|
*/
|
||||||
|
public class SpotLight extends Light implements Savable {
|
||||||
|
|
||||||
|
protected Vector3f position = new Vector3f();
|
||||||
|
protected Vector3f direction = new Vector3f(0,-1,0);
|
||||||
|
protected float spotInnerAngle = FastMath.QUARTER_PI / 8;
|
||||||
|
protected float spotOuterAngle = FastMath.QUARTER_PI / 6;
|
||||||
|
protected float spotRange = 100;
|
||||||
|
protected float invSpotRange = 1 / 100;
|
||||||
|
protected float packedAngleCos=0;
|
||||||
|
|
||||||
|
public SpotLight() {
|
||||||
|
super();
|
||||||
|
computePackedCos();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computePackedCos() {
|
||||||
|
float innerCos=FastMath.cos(spotInnerAngle);
|
||||||
|
float outerCos=FastMath.cos(spotOuterAngle);
|
||||||
|
packedAngleCos=(int)(innerCos*1000);
|
||||||
|
packedAngleCos+=outerCos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void computeLastDistance(Spatial owner) {
|
||||||
|
if (owner.getWorldBound() != null) {
|
||||||
|
BoundingVolume bv = owner.getWorldBound();
|
||||||
|
lastDistance = bv.distanceSquaredTo(position);
|
||||||
|
} else {
|
||||||
|
lastDistance = owner.getWorldTranslation().distanceSquared(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.Spot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3f getDirection() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirection(Vector3f direction) {
|
||||||
|
this.direction.set(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3f getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
this.position.set(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSpotRange() {
|
||||||
|
return spotRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the range of the light influence.
|
||||||
|
* <p>
|
||||||
|
* Setting a non-zero range indicates the light should use attenuation.
|
||||||
|
* If a pixel's distance to this light's position
|
||||||
|
* is greater than the light's range, then the pixel will not be
|
||||||
|
* effected by this light, if the distance is less than the range, then
|
||||||
|
* the magnitude of the influence is equal to distance / range.
|
||||||
|
*
|
||||||
|
* @param spotRange the range of the light influence.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If spotRange is negative
|
||||||
|
*/
|
||||||
|
public void setSpotRange(float spotRange) {
|
||||||
|
if (spotRange < 0) {
|
||||||
|
throw new IllegalArgumentException("SpotLight range cannot be negative");
|
||||||
|
}
|
||||||
|
this.spotRange = spotRange;
|
||||||
|
if (spotRange != 0) {
|
||||||
|
this.invSpotRange = 1 / spotRange;
|
||||||
|
} else {
|
||||||
|
this.invSpotRange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for internal use only
|
||||||
|
* @return the inverse of the spot range
|
||||||
|
*/
|
||||||
|
public float getInvSpotRange() {
|
||||||
|
return invSpotRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the spot inner angle
|
||||||
|
* @return the spot inner angle
|
||||||
|
*/
|
||||||
|
public float getSpotInnerAngle() {
|
||||||
|
return spotInnerAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the inner angle of the cone of influence.
|
||||||
|
* This angle is the angle between the spot direction axis and the inner border of the cone of influence.
|
||||||
|
* @param spotInnerAngle
|
||||||
|
*/
|
||||||
|
public void setSpotInnerAngle(float spotInnerAngle) {
|
||||||
|
this.spotInnerAngle = spotInnerAngle;
|
||||||
|
computePackedCos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the spot outer angle
|
||||||
|
* @return the spot outer angle
|
||||||
|
*/
|
||||||
|
public float getSpotOuterAngle() {
|
||||||
|
return spotOuterAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the outer angle of the cone of influence.
|
||||||
|
* This angle is the angle between the spot direction axis and the outer border of the cone of influence.
|
||||||
|
* this should be greater than the inner angle or the result will be unexpected.
|
||||||
|
* @param spotOuterAngle
|
||||||
|
*/
|
||||||
|
public void setSpotOuterAngle(float spotOuterAngle) {
|
||||||
|
this.spotOuterAngle = spotOuterAngle;
|
||||||
|
computePackedCos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for internal use only
|
||||||
|
* @return the cosines of the inner and outter angle packed in a float
|
||||||
|
*/
|
||||||
|
public float getPackedAngleCos() {
|
||||||
|
return packedAngleCos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JmeExporter ex) throws IOException {
|
||||||
|
super.write(ex);
|
||||||
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
|
oc.write(direction, "direction", new Vector3f());
|
||||||
|
oc.write(position, "position", new Vector3f());
|
||||||
|
oc.write(spotInnerAngle, "spotInnerAngle", FastMath.QUARTER_PI / 8);
|
||||||
|
oc.write(spotOuterAngle, "spotOuterAngle", FastMath.QUARTER_PI / 6);
|
||||||
|
oc.write(spotRange, "spotRange", 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(JmeImporter im) throws IOException {
|
||||||
|
super.read(im);
|
||||||
|
InputCapsule ic = im.getCapsule(this);
|
||||||
|
spotInnerAngle = ic.readFloat("spotInnerAngle", FastMath.QUARTER_PI / 8);
|
||||||
|
spotOuterAngle = ic.readFloat("spotOuterAngle", FastMath.QUARTER_PI / 6);
|
||||||
|
direction = (Vector3f) ic.readSavable("direction", new Vector3f());
|
||||||
|
position = (Vector3f) ic.readSavable("position", new Vector3f());
|
||||||
|
spotRange = ic.readFloat("spotRange", 100);
|
||||||
|
if (spotRange != 0) {
|
||||||
|
this.invSpotRange = 1 / spotRange;
|
||||||
|
} else {
|
||||||
|
this.invSpotRange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
* Copyright (c) 2009-2010 jMonkeyEngine All rights reserved.
|
||||||
* All rights reserved.
|
* <p/>
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* <p/>
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
*
|
* <p/>
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
* <p/>
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package com.jme3.material;
|
package com.jme3.material;
|
||||||
|
|
||||||
@ -46,7 +44,9 @@ import com.jme3.light.DirectionalLight;
|
|||||||
import com.jme3.light.Light;
|
import com.jme3.light.Light;
|
||||||
import com.jme3.light.LightList;
|
import com.jme3.light.LightList;
|
||||||
import com.jme3.light.PointLight;
|
import com.jme3.light.PointLight;
|
||||||
|
import com.jme3.light.SpotLight;
|
||||||
import com.jme3.material.TechniqueDef.LightMode;
|
import com.jme3.material.TechniqueDef.LightMode;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Quaternion;
|
import com.jme3.math.Quaternion;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.math.Vector4f;
|
import com.jme3.math.Vector4f;
|
||||||
@ -72,12 +72,15 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>Material</code> describes the rendering style for a given
|
* <code>Material</code> describes the rendering style for a given
|
||||||
* {@link Geometry}.
|
* {
|
||||||
*
|
* <p/>
|
||||||
* <p>A material is essentially a list of {@link MatParam parameters}, those parameters
|
* @link Geometry}.
|
||||||
* map to uniforms which are defined in a shader.
|
* <p/>
|
||||||
* Setting the parameters can modify the behavior of a shader.
|
* <p>A material is essentially a list of {
|
||||||
*
|
* @link MatParam parameters}, those parameters map to uniforms which are
|
||||||
|
* defined in a shader. Setting the parameters can modify the behavior of a
|
||||||
|
* shader.
|
||||||
|
* <p/>
|
||||||
* @author Kirill Vainer
|
* @author Kirill Vainer
|
||||||
*/
|
*/
|
||||||
public class Material implements Cloneable, Savable, Comparable<Material> {
|
public class Material implements Cloneable, Savable, Comparable<Material> {
|
||||||
@ -96,7 +99,6 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive);
|
additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive);
|
||||||
additiveLight.setDepthWrite(false);
|
additiveLight.setDepthWrite(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String assetName;
|
private String assetName;
|
||||||
private MaterialDef def;
|
private MaterialDef def;
|
||||||
private ListMap<String, MatParam> paramValues = new ListMap<String, MatParam>();
|
private ListMap<String, MatParam> paramValues = new ListMap<String, MatParam>();
|
||||||
@ -364,7 +366,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
} else {
|
} else {
|
||||||
logger.log(Level.WARNING, "Material parameter {0} uses a deprecated naming convention use {1} instead ", new Object[]{name, newName});
|
logger.log(Level.WARNING, "Material parameter {0} uses a deprecated naming convention use {1} instead ", new Object[]{name, newName});
|
||||||
}
|
}
|
||||||
}else if (paramDef == null){
|
} else if (paramDef == null) {
|
||||||
throw new IllegalArgumentException("Material parameter is not defined: " + name);
|
throw new IllegalArgumentException("Material parameter is not defined: " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +406,8 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
* @param name the name of the parameter to clear
|
* @param name the name of the parameter to clear
|
||||||
*/
|
*/
|
||||||
public void clearParam(String name) {
|
public void clearParam(String name) {
|
||||||
//On removal, we don't check if the param exists in the paramDef, and just go on with the process.
|
//On removal, we don't check if the param exists in the paramDef, and just go on with the process.
|
||||||
// name = checkSetParam(null, name);
|
// name = checkSetParam(null, name);
|
||||||
|
|
||||||
MatParam matParam = getParam(name);
|
MatParam matParam = getParam(name);
|
||||||
if (matParam != null) {
|
if (matParam != null) {
|
||||||
@ -435,8 +437,9 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
name = checkSetParam(null, name);
|
name = checkSetParam(null, name);
|
||||||
|
|
||||||
MatParamTexture val = getTextureParam(name);
|
MatParamTexture val = getTextureParam(name);
|
||||||
if (val == null)
|
if (val == null) {
|
||||||
throw new IllegalArgumentException("The given texture parameter is not set.");
|
throw new IllegalArgumentException("The given texture parameter is not set.");
|
||||||
|
}
|
||||||
|
|
||||||
int texUnit = val.getUnit();
|
int texUnit = val.getUnit();
|
||||||
paramValues.remove(name);
|
paramValues.remove(name);
|
||||||
@ -492,7 +495,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
*/
|
*/
|
||||||
public void setTexture(String name, Texture value) {
|
public void setTexture(String name, Texture value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
// clear it
|
// clear it
|
||||||
clearTextureParam(name);
|
clearTextureParam(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -625,15 +628,17 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
protected void updateLightListUniforms(Shader shader, Geometry g, int numLights) {
|
protected void updateLightListUniforms(Shader shader, Geometry g, int numLights) {
|
||||||
if (numLights == 0){ // this shader does not do lighting, ignore.
|
if (numLights == 0) { // this shader does not do lighting, ignore.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LightList lightList = g.getWorldLightList();
|
LightList lightList = g.getWorldLightList();
|
||||||
Uniform lightColor = shader.getUniform("g_LightColor");
|
Uniform lightColor = shader.getUniform("g_LightColor");
|
||||||
Uniform lightPos = shader.getUniform("g_LightPosition");
|
Uniform lightPos = shader.getUniform("g_LightPosition");
|
||||||
|
Uniform lightDir = shader.getUniform("g_LightDirection");
|
||||||
lightColor.setVector4Length(numLights);
|
lightColor.setVector4Length(numLights);
|
||||||
lightPos.setVector4Length(numLights);
|
lightPos.setVector4Length(numLights);
|
||||||
|
lightDir.setVector4Length(numLights);
|
||||||
|
|
||||||
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
|
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
|
||||||
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList));
|
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList));
|
||||||
@ -662,12 +667,19 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
case Point:
|
case Point:
|
||||||
PointLight pl = (PointLight) l;
|
PointLight pl = (PointLight) l;
|
||||||
Vector3f pos = pl.getPosition();
|
Vector3f pos = pl.getPosition();
|
||||||
float invRadius = pl.getRadius();
|
float invRadius = pl.getInvRadius();
|
||||||
if (invRadius != 0) {
|
|
||||||
invRadius = 1f / invRadius;
|
|
||||||
}
|
|
||||||
lightPos.setVector4InArray(pos.getX(), pos.getY(), pos.getZ(), invRadius, lightIndex);
|
lightPos.setVector4InArray(pos.getX(), pos.getY(), pos.getZ(), invRadius, lightIndex);
|
||||||
break;
|
break;
|
||||||
|
case Spot:
|
||||||
|
SpotLight sl = (SpotLight) l;
|
||||||
|
Vector3f pos2 = sl.getPosition();
|
||||||
|
Vector3f dir2 = sl.getDirection();
|
||||||
|
float invRange = sl.getInvSpotRange();
|
||||||
|
float spotAngleCos = sl.getPackedAngleCos();
|
||||||
|
|
||||||
|
lightPos.setVector4InArray(pos2.getX(), pos2.getY(), pos2.getZ(), invRange, lightIndex);
|
||||||
|
lightDir.setVector4InArray(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos, lightIndex);
|
||||||
|
break;
|
||||||
case Ambient:
|
case Ambient:
|
||||||
// skip this light. Does not increase lightIndex
|
// skip this light. Does not increase lightIndex
|
||||||
continue;
|
continue;
|
||||||
@ -679,7 +691,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
lightIndex++;
|
lightIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (lightIndex < numLights){
|
while (lightIndex < numLights) {
|
||||||
lightColor.setVector4InArray(0f, 0f, 0f, 0f, lightIndex);
|
lightColor.setVector4InArray(0f, 0f, 0f, 0f, lightIndex);
|
||||||
lightPos.setVector4InArray(0f, 0f, 0f, 0f, lightIndex);
|
lightPos.setVector4InArray(0f, 0f, 0f, 0f, lightIndex);
|
||||||
|
|
||||||
@ -689,6 +701,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
|
|
||||||
protected void renderMultipassLighting(Shader shader, Geometry g, Renderer r) {
|
protected void renderMultipassLighting(Shader shader, Geometry g, Renderer r) {
|
||||||
LightList lightList = g.getWorldLightList();
|
LightList lightList = g.getWorldLightList();
|
||||||
|
Uniform lightDir = shader.getUniform("g_LightDirection");
|
||||||
Uniform lightColor = shader.getUniform("g_LightColor");
|
Uniform lightColor = shader.getUniform("g_LightColor");
|
||||||
Uniform lightPos = shader.getUniform("g_LightPosition");
|
Uniform lightPos = shader.getUniform("g_LightPosition");
|
||||||
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
|
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
|
||||||
@ -740,10 +753,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
case Point:
|
case Point:
|
||||||
PointLight pl = (PointLight) l;
|
PointLight pl = (PointLight) l;
|
||||||
Vector3f pos = pl.getPosition();
|
Vector3f pos = pl.getPosition();
|
||||||
float invRadius = pl.getRadius();
|
float invRadius = pl.getInvRadius();
|
||||||
if (invRadius != 0) {
|
|
||||||
invRadius = 1f / invRadius;
|
|
||||||
}
|
|
||||||
Quaternion q2;
|
Quaternion q2;
|
||||||
if (lightPos.getValue() != null) {
|
if (lightPos.getValue() != null) {
|
||||||
q2 = (Quaternion) lightPos.getValue();
|
q2 = (Quaternion) lightPos.getValue();
|
||||||
@ -752,6 +762,31 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
}
|
}
|
||||||
q2.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
|
q2.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
|
||||||
lightPos.setValue(VarType.Vector4, q2);
|
lightPos.setValue(VarType.Vector4, q2);
|
||||||
|
break;
|
||||||
|
case Spot:
|
||||||
|
SpotLight sl = (SpotLight) l;
|
||||||
|
Vector3f pos2 = sl.getPosition();
|
||||||
|
Vector3f dir2 = sl.getDirection();
|
||||||
|
float invRange = sl.getInvSpotRange();
|
||||||
|
float spotAngleCos = sl.getPackedAngleCos();
|
||||||
|
|
||||||
|
Quaternion q3,q4;
|
||||||
|
if (lightPos.getValue() != null) {
|
||||||
|
q3 = (Quaternion) lightPos.getValue();
|
||||||
|
} else {
|
||||||
|
q3 = new Quaternion();
|
||||||
|
}
|
||||||
|
q3.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
|
||||||
|
lightPos.setValue(VarType.Vector4, q3);
|
||||||
|
|
||||||
|
if (lightDir.getValue() != null) {
|
||||||
|
q4 = (Quaternion) lightDir.getValue();
|
||||||
|
} else {
|
||||||
|
q4 = new Quaternion();
|
||||||
|
}
|
||||||
|
q4.set(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos);
|
||||||
|
lightDir.setValue(VarType.Vector4, q4);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
|
throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
|
||||||
@ -1019,24 +1054,24 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
boolean enableVcolor = false;
|
boolean enableVcolor = false;
|
||||||
boolean separateTexCoord = false;
|
boolean separateTexCoord = false;
|
||||||
|
|
||||||
if (im.getFormatVersion() == 0){
|
if (im.getFormatVersion() == 0) {
|
||||||
// Enable compatibility with old models
|
// Enable compatibility with old models
|
||||||
if (defName.equalsIgnoreCase("Common/MatDefs/Misc/VertexColor.j3md")){
|
if (defName.equalsIgnoreCase("Common/MatDefs/Misc/VertexColor.j3md")) {
|
||||||
// Using VertexColor, switch to Unshaded and set VertexColor=true
|
// Using VertexColor, switch to Unshaded and set VertexColor=true
|
||||||
enableVcolor = true;
|
enableVcolor = true;
|
||||||
defName = "Common/MatDefs/Misc/Unshaded.j3md";
|
defName = "Common/MatDefs/Misc/Unshaded.j3md";
|
||||||
}else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/SimpleTextured.j3md")
|
} else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/SimpleTextured.j3md")
|
||||||
|| defName.equalsIgnoreCase("Common/MatDefs/Misc/SolidColor.j3md")){
|
|| defName.equalsIgnoreCase("Common/MatDefs/Misc/SolidColor.j3md")) {
|
||||||
// Using SimpleTextured/SolidColor, just switch to Unshaded
|
// Using SimpleTextured/SolidColor, just switch to Unshaded
|
||||||
defName = "Common/MatDefs/Misc/Unshaded.j3md";
|
defName = "Common/MatDefs/Misc/Unshaded.j3md";
|
||||||
}else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/WireColor.j3md")){
|
} else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/WireColor.j3md")) {
|
||||||
// Using WireColor, set wireframe renderstate = true and use Unshaded
|
// Using WireColor, set wireframe renderstate = true and use Unshaded
|
||||||
getAdditionalRenderState().setWireframe(true);
|
getAdditionalRenderState().setWireframe(true);
|
||||||
defName = "Common/MatDefs/Misc/Unshaded.j3md";
|
defName = "Common/MatDefs/Misc/Unshaded.j3md";
|
||||||
}else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/Unshaded.j3md")){
|
} else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/Unshaded.j3md")) {
|
||||||
// Uses unshaded, ensure that the proper param is set
|
// Uses unshaded, ensure that the proper param is set
|
||||||
MatParam value = params.get("SeperateTexCoord");
|
MatParam value = params.get("SeperateTexCoord");
|
||||||
if (value != null && ((Boolean)value.getValue()) == true){
|
if (value != null && ((Boolean) value.getValue()) == true) {
|
||||||
params.remove("SeperateTexCoord");
|
params.remove("SeperateTexCoord");
|
||||||
separateTexCoord = true;
|
separateTexCoord = true;
|
||||||
}
|
}
|
||||||
@ -1066,10 +1101,10 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
|
|||||||
paramValues.put(param.getName(), param);
|
paramValues.put(param.getName(), param);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableVcolor){
|
if (enableVcolor) {
|
||||||
setBoolean("VertexColor", true);
|
setBoolean("VertexColor", true);
|
||||||
}
|
}
|
||||||
if (separateTexCoord){
|
if (separateTexCoord) {
|
||||||
setBoolean("SeparateTexCoord", true);
|
setBoolean("SeparateTexCoord", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ varying vec3 vnPosition;
|
|||||||
varying vec3 vViewDir;
|
varying vec3 vViewDir;
|
||||||
varying vec4 vLightDir;
|
varying vec4 vLightDir;
|
||||||
varying vec4 vnLightDir;
|
varying vec4 vnLightDir;
|
||||||
|
varying vec4 lightVec;
|
||||||
|
varying vec4 spotVec;
|
||||||
|
|
||||||
|
|
||||||
#ifdef DIFFUSEMAP
|
#ifdef DIFFUSEMAP
|
||||||
@ -644,6 +646,20 @@ void main(){
|
|||||||
vec4 diffuseColor = vec4(1.0);
|
vec4 diffuseColor = vec4(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
float spotFallOff = 1.0;
|
||||||
|
if(spotVec.w!=0){
|
||||||
|
vec3 L=normalize(lightVec.xyz);
|
||||||
|
vec3 spotdir = normalize(spotVec.xyz);
|
||||||
|
float curAngleCos = dot(-L, spotdir);
|
||||||
|
float innerAngleCos = spotVec.w;
|
||||||
|
float outerAngleCos = lightVec.w;
|
||||||
|
float innerMinusOuter = innerAngleCos - outerAngleCos;
|
||||||
|
spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
|
||||||
|
if(spotFallOff<=0.0){
|
||||||
|
gl_FragColor = AmbientSum * diffuseColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------
|
//---------------------
|
||||||
// normal calculations
|
// normal calculations
|
||||||
@ -665,7 +681,7 @@ void main(){
|
|||||||
vec4 lightDir = vLightDir;
|
vec4 lightDir = vLightDir;
|
||||||
lightDir.xyz = normalize(lightDir.xyz);
|
lightDir.xyz = normalize(lightDir.xyz);
|
||||||
|
|
||||||
vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz);
|
vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz)*spotFallOff;
|
||||||
|
|
||||||
vec4 specularColor = vec4(1.0);
|
vec4 specularColor = vec4(1.0);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ uniform mat4 g_ViewMatrix;
|
|||||||
|
|
||||||
uniform vec4 g_LightColor;
|
uniform vec4 g_LightColor;
|
||||||
uniform vec4 g_LightPosition;
|
uniform vec4 g_LightPosition;
|
||||||
|
uniform vec4 g_LightDirection;
|
||||||
uniform vec4 g_AmbientLightColor;
|
uniform vec4 g_AmbientLightColor;
|
||||||
|
|
||||||
uniform float m_Shininess;
|
uniform float m_Shininess;
|
||||||
@ -23,6 +24,9 @@ varying vec3 vnViewDir;
|
|||||||
varying vec4 vLightDir;
|
varying vec4 vLightDir;
|
||||||
varying vec4 vnLightDir;
|
varying vec4 vnLightDir;
|
||||||
|
|
||||||
|
varying vec4 lightVec;
|
||||||
|
varying vec4 spotVec;
|
||||||
|
|
||||||
varying vec4 AmbientSum;
|
varying vec4 AmbientSum;
|
||||||
varying vec4 DiffuseSum;
|
varying vec4 DiffuseSum;
|
||||||
varying vec4 SpecularSum;
|
varying vec4 SpecularSum;
|
||||||
@ -38,7 +42,7 @@ varying vec4 SpecularSum;
|
|||||||
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
|
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
|
||||||
float posLight = step(0.5, color.w);
|
float posLight = step(0.5, color.w);
|
||||||
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
|
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
|
||||||
|
lightVec.xyz = tempVec;
|
||||||
float dist = length(tempVec);
|
float dist = length(tempVec);
|
||||||
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
|
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
|
||||||
lightDir.xyz = tempVec / vec3(dist);
|
lightDir.xyz = tempVec / vec3(dist);
|
||||||
@ -54,7 +58,7 @@ void main(){
|
|||||||
vec3 wvNormal = normalize(g_NormalMatrix * inNormal);
|
vec3 wvNormal = normalize(g_NormalMatrix * inNormal);
|
||||||
vec3 viewDir = normalize(-wvPosition);
|
vec3 viewDir = normalize(-wvPosition);
|
||||||
|
|
||||||
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz, g_LightColor.w));
|
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz,clamp(g_LightColor.w,0.0,1.0)));
|
||||||
wvLightPos.w = g_LightPosition.w;
|
wvLightPos.w = g_LightPosition.w;
|
||||||
vec4 lightColor = g_LightColor;
|
vec4 lightColor = g_LightColor;
|
||||||
|
|
||||||
@ -85,6 +89,11 @@ void main(){
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//computing spot direction in view space and unpacking spotlight cos
|
||||||
|
spotVec=(g_ViewMatrix *vec4(g_LightDirection.xyz,0.0) );
|
||||||
|
spotVec.w=floor(g_LightDirection.w)*0.001;
|
||||||
|
lightVec.w = fract(g_LightDirection.w);
|
||||||
|
|
||||||
AmbientSum = vec4(0.2, 0.2, 0.2, 1.0) * g_AmbientLightColor; // Default: ambient color is dark gray
|
AmbientSum = vec4(0.2, 0.2, 0.2, 1.0) * g_AmbientLightColor; // Default: ambient color is dark gray
|
||||||
DiffuseSum = lightColor;
|
DiffuseSum = lightColor;
|
||||||
SpecularSum = lightColor;
|
SpecularSum = lightColor;
|
||||||
|
159
engine/src/test/jme3test/light/TestSpotLight.java
Normal file
159
engine/src/test/jme3test/light/TestSpotLight.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jme3test.light;
|
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.light.AmbientLight;
|
||||||
|
import com.jme3.light.SpotLight;
|
||||||
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Quaternion;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.scene.shape.Box;
|
||||||
|
import com.jme3.scene.shape.Sphere;
|
||||||
|
import com.jme3.texture.Texture.WrapMode;
|
||||||
|
import com.jme3.util.TangentBinormalGenerator;
|
||||||
|
|
||||||
|
public class TestSpotLight extends SimpleApplication {
|
||||||
|
|
||||||
|
private Vector3f lightTarget = new Vector3f(12, 3.5f, 30);
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
TestSpotLight app = new TestSpotLight();
|
||||||
|
app.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
SpotLight spot;
|
||||||
|
Geometry lightMdl;
|
||||||
|
public void setupLighting(){
|
||||||
|
AmbientLight al=new AmbientLight();
|
||||||
|
al.setColor(ColorRGBA.White.mult(0.8f));
|
||||||
|
rootNode.addLight(al);
|
||||||
|
|
||||||
|
spot=new SpotLight();
|
||||||
|
|
||||||
|
spot.setSpotRange(1000);
|
||||||
|
spot.setSpotInnerAngle(5*FastMath.DEG_TO_RAD);
|
||||||
|
spot.setSpotOuterAngle(10*FastMath.DEG_TO_RAD);
|
||||||
|
spot.setPosition(new Vector3f(77.70334f, 34.013165f, 27.1017f));
|
||||||
|
spot.setDirection(lightTarget.subtract(spot.getPosition()));
|
||||||
|
spot.setColor(ColorRGBA.White.mult(2));
|
||||||
|
rootNode.addLight(spot);
|
||||||
|
|
||||||
|
|
||||||
|
// PointLight pl=new PointLight();
|
||||||
|
// pl.setPosition(new Vector3f(77.70334f, 34.013165f, 27.1017f));
|
||||||
|
// pl.setRadius(1000);
|
||||||
|
// pl.setColor(ColorRGBA.White.mult(2));
|
||||||
|
// rootNode.addLight(pl);
|
||||||
|
lightMdl = new Geometry("Light", new Sphere(10, 10, 0.1f));
|
||||||
|
lightMdl.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m"));
|
||||||
|
lightMdl.setLocalTranslation(new Vector3f(77.70334f, 34.013165f, 27.1017f));
|
||||||
|
lightMdl.setLocalScale(5);
|
||||||
|
rootNode.attachChild(lightMdl);
|
||||||
|
|
||||||
|
// DirectionalLight dl = new DirectionalLight();
|
||||||
|
// dl.setDirection(lightTarget.subtract(new Vector3f(77.70334f, 34.013165f, 27.1017f)));
|
||||||
|
// dl.setColor(ColorRGBA.White.mult(2));
|
||||||
|
// rootNode.addLight(dl);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupFloor(){
|
||||||
|
Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
|
||||||
|
mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat);
|
||||||
|
mat.getTextureParam("NormalMap").getTextureValue().setWrap(WrapMode.Repeat);
|
||||||
|
// mat.getTextureParam("ParallaxMap").getTextureValue().setWrap(WrapMode.Repeat);
|
||||||
|
mat.setFloat("Shininess",3);
|
||||||
|
// mat.setBoolean("VertexLighting", true);
|
||||||
|
|
||||||
|
|
||||||
|
Box floor = new Box(Vector3f.ZERO, 50, 1f, 50);
|
||||||
|
TangentBinormalGenerator.generate(floor);
|
||||||
|
floor.scaleTextureCoordinates(new Vector2f(5, 5));
|
||||||
|
Geometry floorGeom = new Geometry("Floor", floor);
|
||||||
|
floorGeom.setMaterial(mat);
|
||||||
|
floorGeom.setShadowMode(ShadowMode.Receive);
|
||||||
|
rootNode.attachChild(floorGeom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void setupSignpost(){
|
||||||
|
Spatial signpost = assetManager.loadModel("Models/Sign Post/Sign Post.mesh.xml");
|
||||||
|
Material mat = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m");
|
||||||
|
// mat.setBoolean("VertexLighting", true);
|
||||||
|
signpost.setMaterial(mat);
|
||||||
|
signpost.rotate(0, FastMath.HALF_PI, 0);
|
||||||
|
signpost.setLocalTranslation(12, 3.5f, 30);
|
||||||
|
signpost.setLocalScale(4);
|
||||||
|
signpost.setShadowMode(ShadowMode.CastAndReceive);
|
||||||
|
TangentBinormalGenerator.generate(signpost);
|
||||||
|
rootNode.attachChild(signpost);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleInitApp() {
|
||||||
|
cam.setLocation(new Vector3f(27.492603f, 29.138166f, -13.232513f));
|
||||||
|
cam.setRotation(new Quaternion(0.25168246f, -0.10547892f, 0.02760565f, 0.96164864f));
|
||||||
|
flyCam.setMoveSpeed(30);
|
||||||
|
|
||||||
|
setupLighting();
|
||||||
|
setupFloor();
|
||||||
|
setupSignpost();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float angle;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleUpdate(float tpf) {
|
||||||
|
super.simpleUpdate(tpf);
|
||||||
|
angle += tpf;
|
||||||
|
angle %= FastMath.TWO_PI;
|
||||||
|
|
||||||
|
spot.setPosition(new Vector3f(FastMath.cos(angle) * 30f, 34.013165f, FastMath.sin(angle) * 30f));
|
||||||
|
lightMdl.setLocalTranslation(spot.getPosition());
|
||||||
|
spot.setDirection(lightTarget.subtract(spot.getPosition()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
219
engine/src/test/jme3test/light/TestSpotLightTerrain.java
Normal file
219
engine/src/test/jme3test/light/TestSpotLightTerrain.java
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package jme3test.light;
|
||||||
|
|
||||||
|
import jme3tools.converters.ImageToAwt;
|
||||||
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.font.BitmapText;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.controls.ActionListener;
|
||||||
|
import com.jme3.input.controls.KeyTrigger;
|
||||||
|
import com.jme3.light.AmbientLight;
|
||||||
|
import com.jme3.light.PointLight;
|
||||||
|
import com.jme3.light.SpotLight;
|
||||||
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Quaternion;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.scene.shape.Sphere;
|
||||||
|
import com.jme3.terrain.geomipmap.TerrainLodControl;
|
||||||
|
import com.jme3.terrain.heightmap.AbstractHeightMap;
|
||||||
|
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
|
||||||
|
import com.jme3.terrain.geomipmap.TerrainQuad;
|
||||||
|
import com.jme3.texture.Texture;
|
||||||
|
import com.jme3.texture.Texture.WrapMode;
|
||||||
|
import com.jme3.util.SkyFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the terrain's lighting texture with normal maps and lights.
|
||||||
|
*
|
||||||
|
* @author bowens
|
||||||
|
*/
|
||||||
|
public class TestSpotLightTerrain extends SimpleApplication {
|
||||||
|
|
||||||
|
private TerrainQuad terrain;
|
||||||
|
Material matTerrain;
|
||||||
|
Material matWire;
|
||||||
|
boolean wireframe = false;
|
||||||
|
boolean triPlanar = false;
|
||||||
|
boolean wardiso = false;
|
||||||
|
boolean minnaert = false;
|
||||||
|
protected BitmapText hintText;
|
||||||
|
PointLight pl;
|
||||||
|
Geometry lightMdl;
|
||||||
|
private float grassScale = 64;
|
||||||
|
private float dirtScale = 16;
|
||||||
|
private float rockScale = 128;
|
||||||
|
SpotLight sl;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestSpotLightTerrain app = new TestSpotLightTerrain();
|
||||||
|
app.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleInitApp() {
|
||||||
|
makeTerrain();
|
||||||
|
flyCam.setMoveSpeed(50);
|
||||||
|
|
||||||
|
sl = new SpotLight();
|
||||||
|
sl.setSpotRange(100);
|
||||||
|
sl.setSpotOuterAngle(20 * FastMath.DEG_TO_RAD);
|
||||||
|
sl.setSpotInnerAngle(15 * FastMath.DEG_TO_RAD);
|
||||||
|
sl.setDirection(new Vector3f(-0.39820394f, -0.73094344f, 0.55421597f));
|
||||||
|
sl.setPosition(new Vector3f(-64.61567f, -87.615425f, -202.41328f));
|
||||||
|
rootNode.addLight(sl);
|
||||||
|
|
||||||
|
AmbientLight ambLight = new AmbientLight();
|
||||||
|
ambLight.setColor(new ColorRGBA(0.8f, 0.8f, 0.8f, 0.2f));
|
||||||
|
rootNode.addLight(ambLight);
|
||||||
|
|
||||||
|
cam.setLocation(new Vector3f(-41.219646f, -84.8363f, -171.67267f));
|
||||||
|
cam.setRotation(new Quaternion(-0.04562731f, 0.89917684f, -0.09668826f, -0.4243236f));
|
||||||
|
sl.setDirection(cam.getDirection());
|
||||||
|
sl.setPosition(cam.getLocation());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleUpdate(float tpf) {
|
||||||
|
super.simpleUpdate(tpf);
|
||||||
|
sl.setDirection(cam.getDirection());
|
||||||
|
sl.setPosition(cam.getLocation());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeTerrain() {
|
||||||
|
// TERRAIN TEXTURE material
|
||||||
|
matTerrain = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
|
||||||
|
matTerrain.setBoolean("useTriPlanarMapping", false);
|
||||||
|
matTerrain.setBoolean("WardIso", true);
|
||||||
|
|
||||||
|
// ALPHA map (for splat textures)
|
||||||
|
matTerrain.setTexture("AlphaMap", assetManager.loadTexture("Textures/Terrain/splat/alpha1.png"));
|
||||||
|
matTerrain.setTexture("AlphaMap_1", assetManager.loadTexture("Textures/Terrain/splat/alpha2.png"));
|
||||||
|
|
||||||
|
// HEIGHTMAP image (for the terrain heightmap)
|
||||||
|
Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png");
|
||||||
|
|
||||||
|
|
||||||
|
// GRASS texture
|
||||||
|
Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
|
||||||
|
grass.setWrap(WrapMode.Repeat);
|
||||||
|
matTerrain.setTexture("DiffuseMap", grass);
|
||||||
|
matTerrain.setFloat("DiffuseMap_0_scale", grassScale);
|
||||||
|
|
||||||
|
// DIRT texture
|
||||||
|
Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg");
|
||||||
|
dirt.setWrap(WrapMode.Repeat);
|
||||||
|
matTerrain.setTexture("DiffuseMap_1", dirt);
|
||||||
|
matTerrain.setFloat("DiffuseMap_1_scale", dirtScale);
|
||||||
|
|
||||||
|
// ROCK texture
|
||||||
|
Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg");
|
||||||
|
rock.setWrap(WrapMode.Repeat);
|
||||||
|
matTerrain.setTexture("DiffuseMap_2", rock);
|
||||||
|
matTerrain.setFloat("DiffuseMap_2_scale", rockScale);
|
||||||
|
|
||||||
|
// BRICK texture
|
||||||
|
Texture brick = assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg");
|
||||||
|
brick.setWrap(WrapMode.Repeat);
|
||||||
|
matTerrain.setTexture("DiffuseMap_3", brick);
|
||||||
|
matTerrain.setFloat("DiffuseMap_3_scale", rockScale);
|
||||||
|
|
||||||
|
// RIVER ROCK texture
|
||||||
|
Texture riverRock = assetManager.loadTexture("Textures/Terrain/Pond/Pond.png");
|
||||||
|
riverRock.setWrap(WrapMode.Repeat);
|
||||||
|
matTerrain.setTexture("DiffuseMap_4", riverRock);
|
||||||
|
matTerrain.setFloat("DiffuseMap_4_scale", rockScale);
|
||||||
|
|
||||||
|
|
||||||
|
Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
|
||||||
|
normalMap0.setWrap(WrapMode.Repeat);
|
||||||
|
Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
|
||||||
|
normalMap1.setWrap(WrapMode.Repeat);
|
||||||
|
Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png");
|
||||||
|
normalMap2.setWrap(WrapMode.Repeat);
|
||||||
|
matTerrain.setTexture("NormalMap", normalMap0);
|
||||||
|
matTerrain.setTexture("NormalMap_1", normalMap2);
|
||||||
|
matTerrain.setTexture("NormalMap_2", normalMap2);
|
||||||
|
matTerrain.setTexture("NormalMap_4", normalMap2);
|
||||||
|
|
||||||
|
// WIREFRAME material
|
||||||
|
matWire = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
|
matWire.getAdditionalRenderState().setWireframe(true);
|
||||||
|
matWire.setColor("Color", ColorRGBA.Green);
|
||||||
|
|
||||||
|
createSky();
|
||||||
|
|
||||||
|
// CREATE HEIGHTMAP
|
||||||
|
AbstractHeightMap heightmap = null;
|
||||||
|
try {
|
||||||
|
//heightmap = new HillHeightMap(1025, 1000, 50, 100, (byte) 3);
|
||||||
|
|
||||||
|
heightmap = new ImageBasedHeightMap(ImageToAwt.convert(heightMapImage.getImage(), false, true, 0), 1f);
|
||||||
|
heightmap.load();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations
|
||||||
|
TerrainLodControl control = new TerrainLodControl(terrain, getCamera());
|
||||||
|
terrain.addControl(control);
|
||||||
|
terrain.setMaterial(matTerrain);
|
||||||
|
terrain.setModelBound(new BoundingBox());
|
||||||
|
terrain.updateModelBound();
|
||||||
|
terrain.setLocalTranslation(0, -100, 0);
|
||||||
|
terrain.setLocalScale(1f, 1f, 1f);
|
||||||
|
rootNode.attachChild(terrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSky() {
|
||||||
|
Texture west = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_west.jpg");
|
||||||
|
Texture east = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_east.jpg");
|
||||||
|
Texture north = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_north.jpg");
|
||||||
|
Texture south = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_south.jpg");
|
||||||
|
Texture up = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_up.jpg");
|
||||||
|
Texture down = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_down.jpg");
|
||||||
|
|
||||||
|
Spatial sky = SkyFactory.createSky(assetManager, west, east, north, south, up, down);
|
||||||
|
rootNode.attachChild(sky);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user