com.sun.prism.es2.ES2PhongShader Maven / Gradle / Ivy
/*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.prism.es2;
import java.util.HashMap;
import java.util.Map;
/**
* TODO: 3D - Need documentation
*/
class ES2PhongShader {
//dimensions:
static ES2Shader shaders[][][][][] = null;
static String vertexShaderSource;
static String mainFragShaderSource;
enum DiffuseState {
NONE,
DIFFUSECOLOR,
TEXTURE
}
enum SpecularState {
NONE,
TEXTURE,
COLOR,
MIX
}
enum SelfIllumState {
NONE,
TEXTURE
}
enum BumpMapState {
NONE,
TEXTURE,
}
static final int lightStateCount = 4;
private static String diffuseShaderParts[] = new String[DiffuseState.values().length];
private static String specularShaderParts[] = new String[SpecularState.values().length];
private static String selfIllumShaderParts[] = new String[SelfIllumState.values().length];
private static String normalMapShaderParts[] = new String[BumpMapState.values().length];
private static String lightingShaderParts[] = new String[lightStateCount];
static {
shaders = new ES2Shader[DiffuseState.values().length][SpecularState.values().length]
[SelfIllumState.values().length][BumpMapState.values().length][lightStateCount];
//NOTE: When creating new shaders, underscore denotes a "shader part"
diffuseShaderParts[DiffuseState.NONE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/diffuse_none.frag"));
diffuseShaderParts[DiffuseState.DIFFUSECOLOR.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/diffuse_color.frag"));
diffuseShaderParts[DiffuseState.TEXTURE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/diffuse_texture.frag"));
specularShaderParts[SpecularState.NONE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/specular_none.frag"));
specularShaderParts[SpecularState.TEXTURE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/specular_texture.frag"));
specularShaderParts[SpecularState.COLOR.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/specular_color.frag"));
specularShaderParts[SpecularState.MIX.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/specular_mix.frag"));
selfIllumShaderParts[SelfIllumState.NONE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/selfIllum_none.frag"));
selfIllumShaderParts[SelfIllumState.TEXTURE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/selfIllum_texture.frag"));
normalMapShaderParts[BumpMapState.NONE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/normalMap_none.frag"));
normalMapShaderParts[BumpMapState.TEXTURE.ordinal()] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/normalMap_texture.frag"));
lightingShaderParts[0] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/main0Lights.frag"));
lightingShaderParts[1] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/main1Light.frag"));
lightingShaderParts[2] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/main2Lights.frag"));
lightingShaderParts[3] =
ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/main3Lights.frag"));
vertexShaderSource = ES2Shader.readStreamIntoString(ES2ResourceFactory.class.getResourceAsStream("glsl/main.vert"));
}
static SpecularState getSpecularState(ES2PhongMaterial material) {
if (material.maps[ES2PhongMaterial.SPECULAR].getTexture() != null) {
return material.specularColorSet ?
SpecularState.MIX : SpecularState.TEXTURE;
}
return material.specularColorSet ?
SpecularState.COLOR : SpecularState.NONE;
}
static ES2Shader getShader(ES2MeshView meshView, ES2Context context) {
ES2PhongMaterial material = meshView.getMaterial();
DiffuseState diffuseState = DiffuseState.DIFFUSECOLOR;
if (material.maps[ES2PhongMaterial.DIFFUSE].getTexture() != null) {
diffuseState = DiffuseState.TEXTURE;
}
SpecularState specularState = getSpecularState(material);
BumpMapState bumpState = BumpMapState.NONE;
if (material.maps[ES2PhongMaterial.BUMP].getTexture() != null) {
bumpState = BumpMapState.TEXTURE;
}
SelfIllumState selfIllumState = SelfIllumState.NONE;
if (material.maps[ES2PhongMaterial.SELF_ILLUM].getTexture() != null) {
selfIllumState = SelfIllumState.TEXTURE;
}
int numLights = 0;
for (ES2Light light : meshView.getLights()) {
if (light != null && light.w > 0) { numLights++; }
}
ES2Shader shader = shaders[diffuseState.ordinal()][specularState.ordinal()]
[selfIllumState.ordinal()][bumpState.ordinal()][numLights];
if (shader == null) {
String fragShader = lightingShaderParts[numLights].replace("vec4 apply_diffuse();", diffuseShaderParts[diffuseState.ordinal()]);
fragShader = fragShader.replace("vec4 apply_specular();", specularShaderParts[specularState.ordinal()]);
fragShader = fragShader.replace("vec3 apply_normal();", normalMapShaderParts[bumpState.ordinal()]);
fragShader = fragShader.replace("vec4 apply_selfIllum();", selfIllumShaderParts[selfIllumState.ordinal()]);
String[] pixelShaders = new String[]{
fragShader
};
//TODO: 3D - should be done in state checking?
Map attributes = new HashMap<>();
attributes.put("pos", 0);
attributes.put("texCoords", 1);
attributes.put("tangent", 2);
Map samplers = new HashMap<>();
samplers.put("diffuseTexture", 0);
samplers.put("specularMap", 1);
samplers.put("normalMap", 2);
samplers.put("selfIllumTexture", 3);
shader = ES2Shader.createFromSource(context, vertexShaderSource, pixelShaders, samplers, attributes, 1, false);
shaders[diffuseState.ordinal()][specularState.ordinal()][selfIllumState.ordinal()]
[bumpState.ordinal()][numLights] = shader;
}
return shader;
}
static void setShaderParamaters(ES2Shader shader, ES2MeshView meshView, ES2Context context) {
ES2PhongMaterial material = meshView.getMaterial();
shader.setConstant("diffuseColor", material.diffuseColor.getRed(),
material.diffuseColor.getGreen(), material.diffuseColor.getBlue(),
material.diffuseColor.getAlpha());
shader.setConstant("specularColor", material.specularColor.getRed(),
material.specularColor.getGreen(), material.specularColor.getBlue(),
material.specularColor.getAlpha());
context.updateTexture(0, material.maps[ES2PhongMaterial.DIFFUSE].getTexture());
context.updateTexture(1, material.maps[ES2PhongMaterial.SPECULAR].getTexture());
context.updateTexture(2, material.maps[ES2PhongMaterial.BUMP].getTexture());
context.updateTexture(3, material.maps[ES2PhongMaterial.SELF_ILLUM].getTexture());
shader.setConstant("ambientColor", meshView.getAmbientLightRed(),
meshView.getAmbientLightGreen(), meshView.getAmbientLightBlue());
for (int i = 0; i < meshView.getLights().length; i++) {
ES2Light light = meshView.getLights()[i];
if (light != null && light.w > 0) {
setLightConstants(i, shader, light);
}
}
}
private static void setLightConstants(int i, ES2Shader shader, ES2Light light) {
shader.setConstant("lights[" + i + "].pos", light.x, light.y, light.z, light.w);
shader.setConstant("lights[" + i + "].color", light.r, light.g, light.b);
shader.setConstant("lights[" + i + "].attn", light.ca, light.la, light.qa, light.isAttenuated);
shader.setConstant("lights[" + i + "].range", light.maxRange);
if (light.isPointLight()) {
shader.setConstant("lights[" + i + "].dir", 0f, 0f, 1f);
} else {
float dirX = light.dirX;
float dirY = light.dirY;
float dirZ = light.dirZ;
float length = (float) Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
shader.setConstant("lights[" + i + "].dir", dirX / length, dirY / length, dirZ / length);
}
if (light.isPointLight() || light.isDirectionalLight()) {
shader.setConstant("lights[" + i + "].cosOuter", -1f); // cos(180)
shader.setConstant("lights[" + i + "].denom", 2f); // cos(0) - cos(180)
shader.setConstant("lights[" + i + "].falloff", 0f);
} else {
// preparing for: I = pow((cosAngle - cosOuter) / (cosInner - cosOuter), falloff);
float cosOuter = (float) Math.cos(Math.toRadians(light.outerAngle));
float cosInner = (float) Math.cos(Math.toRadians(light.innerAngle));
shader.setConstant("lights[" + i + "].cosOuter", cosOuter);
shader.setConstant("lights[" + i + "].denom", cosInner - cosOuter);
shader.setConstant("lights[" + i + "].falloff", light.falloff);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy