use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class UberShader method scatterPhoton.
public void scatterPhoton(ShadingState state, Color power) {
Color diffuse, specular;
// make sure we are on the right side of the material
state.faceforward();
diffuse = getDiffuse(state);
specular = getSpecular(state);
state.storePhoton(state.getRay().getDirection(), power, diffuse);
float d = diffuse.getAverage();
float r = specular.getAverage();
double rnd = state.getRandom(0, 0, 1);
if (rnd < d) {
// photon is scattered
power.mul(diffuse).mul(1.0f / d);
OrthoNormalBasis onb = state.getBasis();
double u = 2 * Math.PI * rnd / d;
double v = state.getRandom(0, 1, 1);
float s = (float) Math.sqrt(v);
float s1 = (float) Math.sqrt(1.0 - v);
Vector3 w = new Vector3((float) Math.cos(u) * s, (float) Math.sin(u) * s, s1);
w = onb.transform(w, new Vector3());
state.traceDiffusePhoton(new Ray(state.getPoint(), w), power);
} else if (rnd < d + r) {
if (glossyness == 0) {
float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection());
power.mul(diffuse).mul(1.0f / d);
// photon is reflected
float dn = 2 * cos;
Vector3 dir = new Vector3();
dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
} else {
float dn = 2.0f * state.getCosND();
// reflected direction
Vector3 refDir = new Vector3();
refDir.x = (dn * state.getNormal().x) + state.getRay().dx;
refDir.y = (dn * state.getNormal().y) + state.getRay().dy;
refDir.z = (dn * state.getNormal().z) + state.getRay().dz;
power.mul(spec).mul(1.0f / r);
OrthoNormalBasis onb = state.getBasis();
double u = 2 * Math.PI * (rnd - r) / r;
double v = state.getRandom(0, 1, 1);
float s = (float) Math.pow(v, 1 / ((1.0f / glossyness) + 1));
float s1 = (float) Math.sqrt(1 - s * s);
Vector3 w = new Vector3((float) Math.cos(u) * s1, (float) Math.sin(u) * s1, s);
w = onb.transform(w, new Vector3());
state.traceReflectionPhoton(new Ray(state.getPoint(), w), power);
}
}
}
use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class GlassShader method scatterPhoton.
public void scatterPhoton(ShadingState state, Color power) {
Color refr = Color.mul(1 - f0, color);
Color refl = Color.mul(f0, color);
float avgR = refl.getAverage();
float avgT = refr.getAverage();
double rnd = state.getRandom(0, 0, 1);
if (rnd < avgR) {
state.faceforward();
// don't reflect internally
if (state.isBehind()) {
return;
}
// photon is reflected
float cos = state.getCosND();
power.mul(refl).mul(1.0f / avgR);
float dn = 2 * cos;
Vector3 dir = new Vector3();
dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
} else if (rnd < avgR + avgT) {
state.faceforward();
// photon is refracted
float cos = state.getCosND();
float neta = state.isBehind() ? eta : 1.0f / eta;
power.mul(refr).mul(1.0f / avgT);
float wK = -neta;
float arg = 1 - (neta * neta * (1 - (cos * cos)));
Vector3 dir = new Vector3();
if (state.isBehind() && absorptionDistance > 0) {
// this ray is inside the object and leaving it
// compute attenuation that occured along the ray
power.mul(Color.mul(-state.getRay().getMax() / absorptionDistance, absorptionColor.copy().opposite()).exp());
}
if (arg < 0) {
// TIR
float dn = 2 * cos;
dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
} else {
float nK = (neta * cos) - (float) Math.sqrt(arg);
dir.x = (-wK * state.getRay().dx) + (nK * state.getNormal().x);
dir.y = (-wK * state.getRay().dy) + (nK * state.getNormal().y);
dir.z = (-wK * state.getRay().dz) + (nK * state.getNormal().z);
state.traceRefractionPhoton(new Ray(state.getPoint(), dir), power);
}
}
}
use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class GlassShader method getRadiance.
public Color getRadiance(ShadingState state) {
if (!state.includeSpecular()) {
return Color.BLACK;
}
Vector3 reflDir = new Vector3();
Vector3 refrDir = new Vector3();
state.faceforward();
float cos = state.getCosND();
boolean inside = state.isBehind();
float neta = inside ? eta : 1.0f / eta;
float dn = 2 * cos;
reflDir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
reflDir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
reflDir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
// refracted ray
float arg = 1 - (neta * neta * (1 - (cos * cos)));
boolean tir = arg < 0;
if (tir) {
refrDir.x = refrDir.y = refrDir.z = 0;
} else {
float nK = (neta * cos) - (float) Math.sqrt(arg);
refrDir.x = (neta * state.getRay().dx) + (nK * state.getNormal().x);
refrDir.y = (neta * state.getRay().dy) + (nK * state.getNormal().y);
refrDir.z = (neta * state.getRay().dz) + (nK * state.getNormal().z);
}
// compute Fresnel terms
float cosTheta1 = Vector3.dot(state.getNormal(), reflDir);
float cosTheta2 = -Vector3.dot(state.getNormal(), refrDir);
float pPara = (cosTheta1 - eta * cosTheta2) / (cosTheta1 + eta * cosTheta2);
float pPerp = (eta * cosTheta1 - cosTheta2) / (eta * cosTheta1 + cosTheta2);
float kr = 0.5f * (pPara * pPara + pPerp * pPerp);
float kt = 1 - kr;
Color absorbtion = null;
if (inside && absorptionDistance > 0) {
// this ray is inside the object and leaving it
// compute attenuation that occured along the ray
absorbtion = Color.mul(-state.getRay().getMax() / absorptionDistance, absorptionColor.copy().opposite()).exp();
if (absorbtion.isBlack()) {
// nothing goes through
return Color.BLACK;
}
}
// refracted ray
Color ret = Color.black();
if (!tir) {
ret.madd(kt, state.traceRefraction(new Ray(state.getPoint(), refrDir), 0)).mul(color);
}
if (!inside || tir) {
ret.add(Color.mul(kr, state.traceReflection(new Ray(state.getPoint(), reflDir), 0)).mul(color));
}
return absorbtion != null ? ret.mul(absorbtion) : ret;
}
use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class FileMesh method generate.
private TriangleMesh generate(int[] tris, float[] verts, boolean smoothNormals) {
ParameterList pl = new ParameterList();
pl.addIntegerArray("triangles", tris);
pl.addPoints("points", InterpolationType.VERTEX, verts);
if (smoothNormals) {
// filled with 0's
float[] normals = new float[verts.length];
Point3 p0 = new Point3();
Point3 p1 = new Point3();
Point3 p2 = new Point3();
Vector3 n = new Vector3();
for (int i3 = 0; i3 < tris.length; i3 += 3) {
int v0 = tris[i3 + 0];
int v1 = tris[i3 + 1];
int v2 = tris[i3 + 2];
p0.set(verts[3 * v0 + 0], verts[3 * v0 + 1], verts[3 * v0 + 2]);
p1.set(verts[3 * v1 + 0], verts[3 * v1 + 1], verts[3 * v1 + 2]);
p2.set(verts[3 * v2 + 0], verts[3 * v2 + 1], verts[3 * v2 + 2]);
// compute normal
Point3.normal(p0, p1, p2, n);
// add face normal to each vertex
// note that these are not normalized so this in fact weights
// each normal by the area of the triangle
normals[3 * v0 + 0] += n.x;
normals[3 * v0 + 1] += n.y;
normals[3 * v0 + 2] += n.z;
normals[3 * v1 + 0] += n.x;
normals[3 * v1 + 1] += n.y;
normals[3 * v1 + 2] += n.z;
normals[3 * v2 + 0] += n.x;
normals[3 * v2 + 1] += n.y;
normals[3 * v2 + 2] += n.z;
}
// normalize all the vectors
for (int i3 = 0; i3 < normals.length; i3 += 3) {
n.set(normals[i3 + 0], normals[i3 + 1], normals[i3 + 2]);
n.normalize();
normals[i3 + 0] = n.x;
normals[i3 + 1] = n.y;
normals[i3 + 2] = n.z;
}
pl.addVectors("normals", InterpolationType.VERTEX, normals);
}
TriangleMesh m = new TriangleMesh();
if (m.update(pl, null)) {
return m;
}
// printed by the mesh itself - no need to repeat it here
return null;
}
use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class BezierMesh method tesselate.
public PrimitiveList tesselate() {
float[] vertices = new float[patches.length * (subdivs + 1) * (subdivs + 1) * 3];
float[] normals = smooth ? new float[patches.length * (subdivs + 1) * (subdivs + 1) * 3] : null;
float[] uvs = new float[patches.length * (subdivs + 1) * (subdivs + 1) * 2];
int[] indices = new int[patches.length * subdivs * subdivs * (quads ? 4 : (2 * 3))];
int vidx = 0, pidx = 0;
float step = 1.0f / subdivs;
int vstride = subdivs + 1;
Point3 p = new Point3();
Vector3 n = smooth ? new Vector3() : null;
for (float[] patch : patches) {
// create patch vertices
for (int i = 0, voff = 0; i <= subdivs; i++) {
float u = i * step;
float[] bu = bernstein(u);
float[] bdu = bernsteinDeriv(u);
for (int j = 0; j <= subdivs; j++, voff += 3) {
float v = j * step;
float[] bv = bernstein(v);
float[] bdv = bernsteinDeriv(v);
getPatchPoint(u, v, patch, bu, bv, bdu, bdv, p, n);
vertices[vidx + voff + 0] = p.x;
vertices[vidx + voff + 1] = p.y;
vertices[vidx + voff + 2] = p.z;
if (smooth) {
normals[vidx + voff + 0] = n.x;
normals[vidx + voff + 1] = n.y;
normals[vidx + voff + 2] = n.z;
}
uvs[(vidx + voff) / 3 * 2 + 0] = u;
uvs[(vidx + voff) / 3 * 2 + 1] = v;
}
}
// generate patch triangles
for (int i = 0, vbase = vidx / 3; i < subdivs; i++) {
for (int j = 0; j < subdivs; j++) {
int v00 = (i + 0) * vstride + (j + 0);
int v10 = (i + 1) * vstride + (j + 0);
int v01 = (i + 0) * vstride + (j + 1);
int v11 = (i + 1) * vstride + (j + 1);
if (quads) {
indices[pidx + 0] = vbase + v01;
indices[pidx + 1] = vbase + v00;
indices[pidx + 2] = vbase + v10;
indices[pidx + 3] = vbase + v11;
pidx += 4;
} else {
// add 2 triangles
indices[pidx + 0] = vbase + v00;
indices[pidx + 1] = vbase + v10;
indices[pidx + 2] = vbase + v01;
indices[pidx + 3] = vbase + v10;
indices[pidx + 4] = vbase + v11;
indices[pidx + 5] = vbase + v01;
pidx += 6;
}
}
}
vidx += vstride * vstride * 3;
}
ParameterList pl = new ParameterList();
pl.addPoints("points", InterpolationType.VERTEX, vertices);
if (quads) {
pl.addIntegerArray("quads", indices);
} else {
pl.addIntegerArray("triangles", indices);
}
pl.addTexCoords("uvs", InterpolationType.VERTEX, uvs);
if (smooth) {
pl.addVectors("normals", InterpolationType.VERTEX, normals);
}
PrimitiveList m = quads ? new QuadMesh() : new TriangleMesh();
m.update(pl, null);
pl.clear(true);
return m;
}
Aggregations