use of com.jme3.shader.Shader in project jmonkeyengine by jMonkeyEngine.
the class GLSLLoader method loadNode.
/**
* Creates a {@link ShaderDependencyNode} from a stream representing shader code.
*
* @param in The input stream containing shader code
* @param nodeName
* @return
* @throws IOException
*/
private ShaderDependencyNode loadNode(Reader reader, String nodeName) {
ShaderDependencyNode node = new ShaderDependencyNode(nodeName);
StringBuilder sb = new StringBuilder();
StringBuilder sbExt = new StringBuilder();
BufferedReader bufReader = null;
try {
bufReader = new BufferedReader(reader);
String ln;
if (!nodeName.equals("[main]")) {
sb.append("// -- begin import ").append(nodeName).append(" --\n");
}
while ((ln = bufReader.readLine()) != null) {
if (ln.trim().startsWith("#import ")) {
ln = ln.trim().substring(8).trim();
if (ln.startsWith("\"") && ln.endsWith("\"") && ln.length() > 3) {
// import user code
// remove quotes to get filename
ln = ln.substring(1, ln.length() - 1);
if (ln.equals(nodeName)) {
throw new IOException("Node depends on itself.");
}
// check cache first
ShaderDependencyNode dependNode = dependCache.get(ln);
if (dependNode == null) {
Reader dependNodeReader = assetManager.loadAsset(new ShaderDependencyKey(ln));
dependNode = loadNode(dependNodeReader, ln);
}
node.addDependency(sb.length(), dependNode);
}
} else if (ln.trim().startsWith("#extension ")) {
sbExt.append(ln).append('\n');
} else {
sb.append(ln).append('\n');
}
}
if (!nodeName.equals("[main]")) {
sb.append("// -- end import ").append(nodeName).append(" --\n");
}
} catch (IOException ex) {
if (bufReader != null) {
try {
bufReader.close();
} catch (IOException ex1) {
}
}
throw new AssetLoadException("Failed to load shader node: " + nodeName, ex);
}
node.setSource(sb.toString());
node.setExtensions(sbExt.toString());
dependCache.put(nodeName, node);
return node;
}
use of com.jme3.shader.Shader in project jmonkeyengine by jMonkeyEngine.
the class GLRenderer method updateShaderData.
public void updateShaderData(Shader shader) {
int id = shader.getId();
boolean needRegister = false;
if (id == -1) {
// create program
id = gl.glCreateProgram();
if (id == 0) {
throw new RendererException("Invalid ID (" + id + ") received when trying to create shader program.");
}
shader.setId(id);
needRegister = true;
}
// If using GLSL 1.5, we bind the outputs for the user
// For versions 3.3 and up, user should use layout qualifiers instead.
boolean bindFragDataRequired = false;
for (ShaderSource source : shader.getSources()) {
if (source.isUpdateNeeded()) {
updateShaderSourceData(source);
}
if (source.getType() == ShaderType.Fragment && source.getLanguage().equals("GLSL150")) {
bindFragDataRequired = true;
}
gl.glAttachShader(id, source.getId());
}
if (bindFragDataRequired) {
// Check if GLSL version is 1.5 for shader
gl3.glBindFragDataLocation(id, 0, "outFragColor");
// For MRT
for (int i = 0; i < limits.get(Limits.FrameBufferMrtAttachments); i++) {
gl3.glBindFragDataLocation(id, i, "outFragData[" + i + "]");
}
}
// Link shaders to program
gl.glLinkProgram(id);
// Check link status
gl.glGetProgram(id, GL.GL_LINK_STATUS, intBuf1);
boolean linkOK = intBuf1.get(0) == GL.GL_TRUE;
String infoLog = null;
if (VALIDATE_SHADER || !linkOK) {
gl.glGetProgram(id, GL.GL_INFO_LOG_LENGTH, intBuf1);
int length = intBuf1.get(0);
if (length > 3) {
// get infos
infoLog = gl.glGetProgramInfoLog(id, length);
}
}
if (linkOK) {
if (infoLog != null) {
logger.log(Level.WARNING, "Shader linked successfully. Linker warnings: \n{0}", infoLog);
} else {
logger.fine("Shader linked successfully.");
}
shader.clearUpdateNeeded();
if (needRegister) {
// Register shader for clean up if it was created in this method.
objManager.registerObject(shader);
statistics.onNewShader();
} else {
// OpenGL spec: uniform locations may change after re-link
resetUniformLocations(shader);
}
} else {
if (infoLog != null) {
throw new RendererException("Shader failed to link, shader:" + shader + "\n" + infoLog);
} else {
throw new RendererException("Shader failed to link, shader:" + shader + "\ninfo: <not provided>");
}
}
}
use of com.jme3.shader.Shader in project jmonkeyengine by jMonkeyEngine.
the class SinglePassAndImageBasedLightingLogic method updateLightListUniforms.
/**
* Uploads the lights in the light list as two uniform arrays.<br/><br/> *
* <p>
* <code>uniform vec4 g_LightColor[numLights];</code><br/> //
* g_LightColor.rgb is the diffuse/specular color of the light.<br/> //
* g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br/> //
* 2 = Spot. <br/> <br/>
* <code>uniform vec4 g_LightPosition[numLights];</code><br/> //
* g_LightPosition.xyz is the position of the light (for point lights)<br/>
* // or the direction of the light (for directional lights).<br/> //
* g_LightPosition.w is the inverse radius (1/r) of the light (for
* attenuation) <br/> </p>
*/
protected int updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights, RenderManager rm, int startIndex, int lastTexUnit) {
if (numLights == 0) {
// this shader does not do lighting, ignore.
return 0;
}
Uniform lightData = shader.getUniform("g_LightData");
//8 lights * max 3
lightData.setVector4Length(numLights * 3);
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
Uniform lightProbeData = shader.getUniform("g_LightProbeData");
lightProbeData.setVector4Length(1);
Uniform lightProbeIrrMap = shader.getUniform("g_IrradianceMap");
Uniform lightProbePemMap = shader.getUniform("g_PrefEnvMap");
lightProbe = null;
if (startIndex != 0) {
// apply additive blending for 2nd and future passes
rm.getRenderer().applyRenderState(ADDITIVE_LIGHT);
ambientColor.setValue(VarType.Vector4, ColorRGBA.Black);
} else {
lightProbe = extractIndirectLights(lightList, true);
ambientColor.setValue(VarType.Vector4, ambientLightColor);
}
//If there is a lightProbe in the list we force it's render on the first pass
if (lightProbe != null) {
BoundingSphere s = (BoundingSphere) lightProbe.getBounds();
lightProbeData.setVector4InArray(lightProbe.getPosition().x, lightProbe.getPosition().y, lightProbe.getPosition().z, 1f / s.getRadius(), 0);
//assigning new texture indexes
int irrUnit = lastTexUnit++;
int pemUnit = lastTexUnit++;
rm.getRenderer().setTexture(irrUnit, lightProbe.getIrradianceMap());
lightProbeIrrMap.setValue(VarType.Int, irrUnit);
rm.getRenderer().setTexture(pemUnit, lightProbe.getPrefilteredEnvMap());
lightProbePemMap.setValue(VarType.Int, pemUnit);
} else {
//Disable IBL for this pass
lightProbeData.setVector4InArray(0, 0, 0, -1, 0);
}
int lightDataIndex = 0;
TempVars vars = TempVars.get();
Vector4f tmpVec = vars.vect4f1;
int curIndex;
int endIndex = numLights + startIndex;
for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) {
Light l = lightList.get(curIndex);
if (l.getType() == Light.Type.Ambient) {
endIndex++;
continue;
}
ColorRGBA color = l.getColor();
if (l.getType() != Light.Type.Probe) {
lightData.setVector4InArray(color.getRed(), color.getGreen(), color.getBlue(), l.getType().getId(), lightDataIndex);
lightDataIndex++;
}
switch(l.getType()) {
case Directional:
DirectionalLight dl = (DirectionalLight) l;
Vector3f dir = dl.getDirection();
//Data directly sent in view space to avoid a matrix mult for each pixel
tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex);
lightDataIndex++;
//PADDING
lightData.setVector4InArray(0, 0, 0, 0, lightDataIndex);
lightDataIndex++;
break;
case Point:
PointLight pl = (PointLight) l;
Vector3f pos = pl.getPosition();
float invRadius = pl.getInvRadius();
tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex);
lightDataIndex++;
//PADDING
lightData.setVector4InArray(0, 0, 0, 0, lightDataIndex);
lightDataIndex++;
break;
case Spot:
SpotLight sl = (SpotLight) l;
Vector3f pos2 = sl.getPosition();
Vector3f dir2 = sl.getDirection();
float invRange = sl.getInvSpotRange();
float spotAngleCos = sl.getPackedAngleCos();
tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex);
lightDataIndex++;
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex);
lightDataIndex++;
break;
default:
throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
}
}
vars.release();
//Padding of unsued buffer space
while (lightDataIndex < numLights * 3) {
lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex);
lightDataIndex++;
}
return curIndex;
}
use of com.jme3.shader.Shader in project jmonkeyengine by jMonkeyEngine.
the class SinglePassLightingLogic method render.
@Override
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
int nbRenderedLights = 0;
Renderer renderer = renderManager.getRenderer();
int batchSize = renderManager.getSinglePassLightBatchSize();
if (lights.size() == 0) {
updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, 0);
renderer.setShader(shader);
renderMeshFromGeometry(renderer, geometry);
} else {
while (nbRenderedLights < lights.size()) {
nbRenderedLights = updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, nbRenderedLights);
renderer.setShader(shader);
renderMeshFromGeometry(renderer, geometry);
}
}
}
use of com.jme3.shader.Shader in project jmonkeyengine by jMonkeyEngine.
the class SinglePassLightingLogic method updateLightListUniforms.
/**
* Uploads the lights in the light list as two uniform arrays.<br/><br/> *
* <p>
* <code>uniform vec4 g_LightColor[numLights];</code><br/> //
* g_LightColor.rgb is the diffuse/specular color of the light.<br/> //
* g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br/> //
* 2 = Spot. <br/> <br/>
* <code>uniform vec4 g_LightPosition[numLights];</code><br/> //
* g_LightPosition.xyz is the position of the light (for point lights)<br/>
* // or the direction of the light (for directional lights).<br/> //
* g_LightPosition.w is the inverse radius (1/r) of the light (for
* attenuation) <br/> </p>
*/
protected int updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights, RenderManager rm, int startIndex) {
if (numLights == 0) {
// this shader does not do lighting, ignore.
return 0;
}
Uniform lightData = shader.getUniform("g_LightData");
//8 lights * max 3
lightData.setVector4Length(numLights * 3);
Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
if (startIndex != 0) {
// apply additive blending for 2nd and future passes
rm.getRenderer().applyRenderState(ADDITIVE_LIGHT);
ambientColor.setValue(VarType.Vector4, ColorRGBA.Black);
} else {
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList, true, ambientLightColor));
}
int lightDataIndex = 0;
TempVars vars = TempVars.get();
Vector4f tmpVec = vars.vect4f1;
int curIndex;
int endIndex = numLights + startIndex;
for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) {
Light l = lightList.get(curIndex);
if (l.getType() == Light.Type.Ambient) {
endIndex++;
continue;
}
ColorRGBA color = l.getColor();
//Color
lightData.setVector4InArray(color.getRed(), color.getGreen(), color.getBlue(), l.getType().getId(), lightDataIndex);
lightDataIndex++;
switch(l.getType()) {
case Directional:
DirectionalLight dl = (DirectionalLight) l;
Vector3f dir = dl.getDirection();
//Data directly sent in view space to avoid a matrix mult for each pixel
tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
// tmpVec.divideLocal(tmpVec.w);
// tmpVec.normalizeLocal();
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex);
lightDataIndex++;
//PADDING
lightData.setVector4InArray(0, 0, 0, 0, lightDataIndex);
lightDataIndex++;
break;
case Point:
PointLight pl = (PointLight) l;
Vector3f pos = pl.getPosition();
float invRadius = pl.getInvRadius();
tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
//tmpVec.divideLocal(tmpVec.w);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex);
lightDataIndex++;
//PADDING
lightData.setVector4InArray(0, 0, 0, 0, lightDataIndex);
lightDataIndex++;
break;
case Spot:
SpotLight sl = (SpotLight) l;
Vector3f pos2 = sl.getPosition();
Vector3f dir2 = sl.getDirection();
float invRange = sl.getInvSpotRange();
float spotAngleCos = sl.getPackedAngleCos();
tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
// tmpVec.divideLocal(tmpVec.w);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex);
lightDataIndex++;
//We transform the spot direction in view space here to save 5 varying later in the lighting shader
//one vec4 less and a vec4 that becomes a vec3
//the downside is that spotAngleCos decoding happens now in the frag shader.
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
tmpVec.normalizeLocal();
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex);
lightDataIndex++;
break;
case Probe:
break;
default:
throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
}
}
vars.release();
//Padding of unsued buffer space
while (lightDataIndex < numLights * 3) {
lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex);
lightDataIndex++;
}
return curIndex;
}
Aggregations