mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
shader optim
This commit is contained in:
parent
df0477a5c3
commit
dc0f2df246
20 changed files with 622 additions and 11 deletions
|
|
@ -16,7 +16,7 @@ import src.GameObject;
|
|||
import h3d.scene.Scene;
|
||||
import h3d.scene.Object;
|
||||
import h3d.scene.Mesh;
|
||||
import h3d.scene.MeshBatch;
|
||||
import src.MeshBatch;
|
||||
import src.MarbleGame;
|
||||
import src.ProfilerUI;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ import collision.SphereCollisionEntity;
|
|||
import src.Sky;
|
||||
import h3d.scene.Mesh;
|
||||
import src.InstanceManager;
|
||||
import h3d.scene.MeshBatch;
|
||||
import src.MeshBatch;
|
||||
import src.DtsObject;
|
||||
import src.PathedInterior;
|
||||
import hxd.Key;
|
||||
|
|
|
|||
440
src/MeshBatch.hx
Normal file
440
src/MeshBatch.hx
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
package src;
|
||||
|
||||
import h3d.scene.RenderContext;
|
||||
import h3d.Matrix;
|
||||
import h3d.scene.MultiMaterial;
|
||||
import hxsl.ShaderList;
|
||||
|
||||
private class BatchData {
|
||||
public var paramsCount:Int;
|
||||
public var maxInstance:Int;
|
||||
public var matIndex:Int;
|
||||
public var indexCount:Int;
|
||||
public var indexStart:Int;
|
||||
public var instanceBuffers:Array<h3d.impl.InstanceBuffer>;
|
||||
public var buffers:Array<h3d.Buffer> = [];
|
||||
public var data:hxd.FloatBuffer;
|
||||
public var params:hxsl.RuntimeShader.AllocParam;
|
||||
public var shader:hxsl.BatchShader;
|
||||
public var shaders:Array<hxsl.Shader>;
|
||||
public var pass:h3d.mat.Pass;
|
||||
public var next:BatchData;
|
||||
|
||||
public function new() {}
|
||||
}
|
||||
|
||||
class MeshBatchPart {
|
||||
public var indexStart:Int;
|
||||
public var indexCount:Int;
|
||||
public var baseVertex:Int;
|
||||
public var bounds:h3d.col.Bounds;
|
||||
|
||||
public function new() {}
|
||||
}
|
||||
|
||||
/**
|
||||
h3d.scene.MeshBatch allows to draw multiple meshed in a single draw call.
|
||||
See samples/MeshBatch.hx for an example.
|
||||
**/
|
||||
class MeshBatch extends MultiMaterial {
|
||||
static var modelViewID = hxsl.Globals.allocID("global.modelView");
|
||||
static var modelViewTransposeID = hxsl.Globals.allocID("global.modelViewTranspose");
|
||||
static var modelViewInverseID = hxsl.Globals.allocID("global.modelViewInverse");
|
||||
static var MAX_BUFFER_ELEMENTS = 4096;
|
||||
|
||||
var instanced:h3d.prim.Instanced;
|
||||
var dataPasses:BatchData;
|
||||
var needUpload = false;
|
||||
|
||||
/**
|
||||
Set if shader list or shader constants has changed, before calling begin()
|
||||
**/
|
||||
public var shadersChanged = true;
|
||||
|
||||
/**
|
||||
The number of instances on this batch
|
||||
**/
|
||||
public var instanceCount(default, null):Int = 0;
|
||||
|
||||
/**
|
||||
* If set, use this position in emitInstance() instead MeshBatch absolute position
|
||||
**/
|
||||
public var worldPosition:Matrix;
|
||||
|
||||
var invWorldPosition:Matrix;
|
||||
|
||||
/**
|
||||
Tells the mesh batch to draw only a subpart of the primitive
|
||||
**/
|
||||
public var primitiveSubPart:MeshBatchPart;
|
||||
|
||||
var primitiveSubBytes:haxe.io.Bytes;
|
||||
|
||||
/**
|
||||
If set, exact bounds will be recalculated during emitInstance (default true)
|
||||
**/
|
||||
public var calcBounds = true;
|
||||
|
||||
var instancedParams:hxsl.Cache.BatchInstanceParams;
|
||||
|
||||
public function new(primitive, ?material, ?parent) {
|
||||
instanced = new h3d.prim.Instanced();
|
||||
instanced.commands = new h3d.impl.InstanceBuffer();
|
||||
instanced.setMesh(primitive);
|
||||
super(instanced, material == null ? null : [material], parent);
|
||||
for (p in this.material.getPasses())
|
||||
@:privateAccess p.batchMode = true;
|
||||
}
|
||||
|
||||
override function onRemove() {
|
||||
super.onRemove();
|
||||
cleanPasses();
|
||||
}
|
||||
|
||||
function cleanPasses() {
|
||||
var alloc = hxd.impl.Allocator.get();
|
||||
while (dataPasses != null) {
|
||||
dataPasses.pass.removeShader(dataPasses.shader);
|
||||
for (b in dataPasses.buffers)
|
||||
alloc.disposeBuffer(b);
|
||||
if (dataPasses.instanceBuffers != null) {
|
||||
for (b in dataPasses.instanceBuffers)
|
||||
b.dispose();
|
||||
}
|
||||
alloc.disposeFloats(dataPasses.data);
|
||||
dataPasses = dataPasses.next;
|
||||
}
|
||||
if (instanced.commands != null)
|
||||
instanced.commands.dispose();
|
||||
shadersChanged = true;
|
||||
}
|
||||
|
||||
function initShadersMapping() {
|
||||
var scene = getScene();
|
||||
if (scene == null)
|
||||
return;
|
||||
cleanPasses();
|
||||
for (index in 0...materials.length) {
|
||||
var mat = materials[index];
|
||||
if (mat == null)
|
||||
continue;
|
||||
var matInfo = @:privateAccess instanced.primitive.getMaterialIndexes(index);
|
||||
for (p in mat.getPasses())
|
||||
@:privateAccess {
|
||||
var ctx = scene.renderer.getPassByName(p.name);
|
||||
if (ctx == null)
|
||||
throw "Could't find renderer pass " + p.name;
|
||||
|
||||
var manager = cast(ctx, shaders.RendererDefaultPass).manager;
|
||||
var shaders = p.getShadersRec();
|
||||
var rt = manager.compileShaders(shaders, false);
|
||||
var shader = manager.shaderCache.makeBatchShader(rt, shaders, instancedParams);
|
||||
|
||||
var b = new BatchData();
|
||||
b.indexCount = matInfo.count;
|
||||
b.indexStart = matInfo.start;
|
||||
b.paramsCount = shader.paramsSize;
|
||||
b.maxInstance = Std.int(MAX_BUFFER_ELEMENTS / b.paramsCount);
|
||||
if (b.maxInstance <= 0)
|
||||
throw "Mesh batch shaders needs at least one perInstance parameter";
|
||||
b.params = shader.params;
|
||||
b.shader = shader;
|
||||
b.pass = p;
|
||||
b.matIndex = index;
|
||||
b.shaders = [null /*link shader*/];
|
||||
p.dynamicParameters = true;
|
||||
p.batchMode = true;
|
||||
|
||||
b.next = dataPasses;
|
||||
dataPasses = b;
|
||||
|
||||
var sl = shaders;
|
||||
while (sl != null) {
|
||||
b.shaders.push(sl.s);
|
||||
sl = sl.next;
|
||||
}
|
||||
shader.Batch_Count = b.maxInstance * b.paramsCount;
|
||||
shader.Batch_HasOffset = primitiveSubPart != null;
|
||||
shader.constBits = (shader.Batch_Count << 1) | (shader.Batch_HasOffset ? 1 : 0);
|
||||
shader.updateConstants(null);
|
||||
}
|
||||
}
|
||||
|
||||
// add batch shaders
|
||||
var p = dataPasses;
|
||||
while (p != null) {
|
||||
@:privateAccess p.pass.addSelfShader(p.shader);
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
|
||||
public function begin(emitCountTip = -1, resizeDown = false) {
|
||||
instanceCount = 0;
|
||||
instanced.initBounds();
|
||||
if (shadersChanged) {
|
||||
initShadersMapping();
|
||||
shadersChanged = false;
|
||||
}
|
||||
|
||||
if (emitCountTip < 0)
|
||||
emitCountTip = 128;
|
||||
var p = dataPasses;
|
||||
var alloc = hxd.impl.Allocator.get();
|
||||
while (p != null) {
|
||||
var size = emitCountTip * p.paramsCount * 4;
|
||||
if (p.data == null || p.data.length < size || (resizeDown && p.data.length > size << 1)) {
|
||||
if (p.data != null)
|
||||
alloc.disposeFloats(p.data);
|
||||
p.data = alloc.allocFloats(size);
|
||||
}
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
|
||||
function syncData(batch:BatchData) {
|
||||
var startPos = batch.paramsCount * instanceCount << 2;
|
||||
// in case we are bigger than emitCountTip
|
||||
if (startPos + (batch.paramsCount << 2) > batch.data.length)
|
||||
batch.data.grow(batch.data.length << 1);
|
||||
|
||||
var p = batch.params;
|
||||
var buf = batch.data;
|
||||
var shaders = batch.shaders;
|
||||
|
||||
var calcInv = false;
|
||||
while (p != null) {
|
||||
var pos = startPos + p.pos;
|
||||
inline function addMatrix(m:h3d.Matrix) {
|
||||
buf[pos++] = m._11;
|
||||
buf[pos++] = m._21;
|
||||
buf[pos++] = m._31;
|
||||
buf[pos++] = m._41;
|
||||
buf[pos++] = m._12;
|
||||
buf[pos++] = m._22;
|
||||
buf[pos++] = m._32;
|
||||
buf[pos++] = m._42;
|
||||
buf[pos++] = m._13;
|
||||
buf[pos++] = m._23;
|
||||
buf[pos++] = m._33;
|
||||
buf[pos++] = m._43;
|
||||
buf[pos++] = m._14;
|
||||
buf[pos++] = m._24;
|
||||
buf[pos++] = m._34;
|
||||
buf[pos++] = m._44;
|
||||
}
|
||||
if (p.perObjectGlobal != null) {
|
||||
if (p.perObjectGlobal.gid == modelViewID) {
|
||||
addMatrix(worldPosition != null ? worldPosition : absPos);
|
||||
} else if (p.perObjectGlobal.gid == modelViewInverseID) {
|
||||
if (worldPosition == null)
|
||||
addMatrix(getInvPos());
|
||||
else {
|
||||
if (!calcInv) {
|
||||
calcInv = true;
|
||||
if (invWorldPosition == null)
|
||||
invWorldPosition = new h3d.Matrix();
|
||||
invWorldPosition.initInverse(worldPosition);
|
||||
}
|
||||
addMatrix(invWorldPosition);
|
||||
}
|
||||
} else if (p.perObjectGlobal.gid == modelViewTransposeID) {
|
||||
var m = worldPosition != null ? worldPosition : absPos;
|
||||
m.transpose();
|
||||
addMatrix(m);
|
||||
m.transpose();
|
||||
} else
|
||||
throw "Unsupported global param " + p.perObjectGlobal.path;
|
||||
p = p.next;
|
||||
continue;
|
||||
}
|
||||
var curShader = shaders[p.instance];
|
||||
switch (p.type) {
|
||||
case TVec(size, _):
|
||||
var v:h3d.Vector = curShader.getParamValue(p.index);
|
||||
switch (size) {
|
||||
case 2:
|
||||
buf[pos++] = v.x;
|
||||
buf[pos++] = v.y;
|
||||
case 3:
|
||||
buf[pos++] = v.x;
|
||||
buf[pos++] = v.y;
|
||||
buf[pos++] = v.z;
|
||||
default:
|
||||
buf[pos++] = v.x;
|
||||
buf[pos++] = v.y;
|
||||
buf[pos++] = v.z;
|
||||
buf[pos++] = v.w;
|
||||
}
|
||||
case TFloat:
|
||||
buf[pos++] = curShader.getParamFloatValue(p.index);
|
||||
case TMat4:
|
||||
var m:h3d.Matrix = curShader.getParamValue(p.index);
|
||||
addMatrix(m);
|
||||
default:
|
||||
throw "Unsupported batch type " + p.type;
|
||||
}
|
||||
p = p.next;
|
||||
}
|
||||
needUpload = true;
|
||||
}
|
||||
|
||||
override function addBoundsRec(b:h3d.col.Bounds, relativeTo:h3d.Matrix) {
|
||||
var old = primitive;
|
||||
primitive = null;
|
||||
super.addBoundsRec(b, relativeTo);
|
||||
primitive = old;
|
||||
if (primitive == null || flags.has(FIgnoreBounds))
|
||||
return;
|
||||
// already transformed in absolute
|
||||
var bounds = primitive.getBounds();
|
||||
if (relativeTo == null)
|
||||
b.add(bounds);
|
||||
else
|
||||
b.addTransform(bounds, relativeTo);
|
||||
}
|
||||
|
||||
public function emitInstance() {
|
||||
if (worldPosition == null)
|
||||
syncPos();
|
||||
var ps = primitiveSubPart;
|
||||
if (ps != null)
|
||||
@:privateAccess {
|
||||
// instanced.tmpBounds.load(primitiveSubPart.bounds);
|
||||
// instanced.tmpBounds.transform(worldPosition == null ? absPos : worldPosition);
|
||||
// instanced.bounds.add(instanced.tmpBounds);
|
||||
|
||||
if (primitiveSubBytes == null) {
|
||||
primitiveSubBytes = haxe.io.Bytes.alloc(128);
|
||||
instanced.commands = null;
|
||||
}
|
||||
if (primitiveSubBytes.length < (instanceCount + 1) * 20) {
|
||||
var next = haxe.io.Bytes.alloc(Std.int(primitiveSubBytes.length * 3 / 2));
|
||||
next.blit(0, primitiveSubBytes, 0, instanceCount * 20);
|
||||
primitiveSubBytes = next;
|
||||
}
|
||||
var p = instanceCount * 20;
|
||||
primitiveSubBytes.setInt32(p, ps.indexCount);
|
||||
primitiveSubBytes.setInt32(p + 4, 1);
|
||||
primitiveSubBytes.setInt32(p + 8, ps.indexStart);
|
||||
primitiveSubBytes.setInt32(p + 12, ps.baseVertex);
|
||||
primitiveSubBytes.setInt32(p + 16, 0);
|
||||
} else if (calcBounds)
|
||||
instanced.addInstanceBounds(worldPosition == null ? absPos : worldPosition);
|
||||
var p = dataPasses;
|
||||
while (p != null) {
|
||||
syncData(p);
|
||||
p = p.next;
|
||||
}
|
||||
instanceCount++;
|
||||
}
|
||||
|
||||
public function disposeBuffers() {
|
||||
if (instanceCount == 0)
|
||||
return;
|
||||
var p = dataPasses;
|
||||
var alloc = hxd.impl.Allocator.get();
|
||||
while (p != null) {
|
||||
for (b in p.buffers)
|
||||
b.dispose();
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
|
||||
override function sync(ctx:RenderContext) {
|
||||
super.sync(ctx);
|
||||
if (instanceCount == 0)
|
||||
return;
|
||||
var p = dataPasses;
|
||||
var alloc = hxd.impl.Allocator.get();
|
||||
var psBytes = primitiveSubBytes;
|
||||
while (p != null) {
|
||||
var index = 0;
|
||||
var start = 0;
|
||||
while (start < instanceCount) {
|
||||
var upload = needUpload;
|
||||
var buf = p.buffers[index];
|
||||
var count = instanceCount - start;
|
||||
if (count > p.maxInstance)
|
||||
count = p.maxInstance;
|
||||
if (buf == null || buf.isDisposed()) {
|
||||
buf = alloc.allocBuffer(MAX_BUFFER_ELEMENTS, 4, UniformDynamic);
|
||||
p.buffers[index] = buf;
|
||||
upload = true;
|
||||
}
|
||||
if (upload)
|
||||
buf.uploadVector(p.data, start * p.paramsCount * 4, count * p.paramsCount);
|
||||
if (psBytes != null) {
|
||||
if (p.instanceBuffers == null)
|
||||
p.instanceBuffers = [];
|
||||
var buf = p.instanceBuffers[index];
|
||||
if (buf == null /*|| buf.isDisposed()*/) {
|
||||
buf = new h3d.impl.InstanceBuffer();
|
||||
var sub = psBytes.sub(start * 20, count * 20);
|
||||
for (i in 0...count)
|
||||
sub.setInt32(i * 20 + 16, i);
|
||||
buf.setBuffer(count, sub);
|
||||
p.instanceBuffers[index] = buf;
|
||||
}
|
||||
}
|
||||
start += count;
|
||||
index++;
|
||||
}
|
||||
while (p.buffers.length > index)
|
||||
alloc.disposeBuffer(p.buffers.pop());
|
||||
p = p.next;
|
||||
}
|
||||
if (psBytes != null) {
|
||||
var prim = cast(primitive, h3d.prim.MeshPrimitive);
|
||||
var offsets = @:privateAccess prim.getBuffer("Batch_Start");
|
||||
if (offsets == null || offsets.vertices < instanceCount || offsets.isDisposed()) {
|
||||
if (offsets != null)
|
||||
offsets.dispose();
|
||||
var tmp = haxe.io.Bytes.alloc(4 * instanceCount);
|
||||
for (i in 0...instanceCount)
|
||||
tmp.setFloat(i << 2, i);
|
||||
offsets = new h3d.Buffer(instanceCount, 1);
|
||||
offsets.uploadBytes(tmp, 0, instanceCount);
|
||||
@:privateAccess prim.addBuffer("Batch_Start", offsets);
|
||||
}
|
||||
}
|
||||
needUpload = false;
|
||||
}
|
||||
|
||||
override function draw(ctx:RenderContext) {
|
||||
var p = dataPasses;
|
||||
while (true) {
|
||||
if (p.pass == ctx.drawPass.pass) {
|
||||
var bufferIndex = ctx.drawPass.index & 0xFFFF;
|
||||
p.shader.Batch_Buffer = p.buffers[bufferIndex];
|
||||
if (p.instanceBuffers == null) {
|
||||
var count = instanceCount - p.maxInstance * bufferIndex;
|
||||
instanced.commands.setCommand(count, p.indexCount, p.indexStart);
|
||||
} else
|
||||
instanced.commands = p.instanceBuffers[bufferIndex];
|
||||
break;
|
||||
}
|
||||
p = p.next;
|
||||
}
|
||||
ctx.uploadParams();
|
||||
var prev = ctx.drawPass.index;
|
||||
ctx.drawPass.index >>= 16;
|
||||
super.draw(ctx);
|
||||
ctx.drawPass.index = prev;
|
||||
}
|
||||
|
||||
override function emit(ctx:RenderContext) {
|
||||
if (instanceCount == 0)
|
||||
return;
|
||||
var p = dataPasses;
|
||||
while (p != null) {
|
||||
var pass = p.pass;
|
||||
// check that the pass is still enable
|
||||
var material = materials[p.matIndex];
|
||||
if (material != null && material.getPass(pass.name) != null) {
|
||||
for (i in 0...p.buffers.length)
|
||||
ctx.emitPass(pass, this).index = i | (p.matIndex << 16);
|
||||
}
|
||||
p = p.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import shaders.RendererDefaultPass;
|
||||
import hxd.Window;
|
||||
import src.ResourceLoader;
|
||||
import shaders.GammaRamp;
|
||||
|
|
@ -38,7 +39,7 @@ class Renderer extends h3d.scene.Renderer {
|
|||
|
||||
public function new() {
|
||||
super();
|
||||
defaultPass = new h3d.pass.Default("default");
|
||||
defaultPass = new RendererDefaultPass("default");
|
||||
allPasses = [defaultPass, depth, normal, shadow];
|
||||
blurShader = new ScreenFx<Blur>(new Blur());
|
||||
copyPass = new h3d.pass.Copy();
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class DefaultCubemapMaterial extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
@ -58,7 +59,7 @@ class DefaultCubemapMaterial extends hxsl.Shader {
|
|||
outNormal = input.normal;
|
||||
// outNormal.x *= -1;
|
||||
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
outLightVec.xyz = -inLightVec * objToTangentSpace;
|
||||
// var cubeVertPos = input.position * cubeTrans;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class DefaultCubemapNormalMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -44,7 +45,7 @@ class DefaultCubemapNormalMaterial extends hxsl.Shader {
|
|||
function vertex() {
|
||||
calculatedUV = input.uv;
|
||||
outLightVec = vec4(0);
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var eyePos = camera.position * mat3x4(global.modelViewInverse);
|
||||
// eyePos.x *= -1;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class DefaultCubemapNormalNoSpecMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -38,7 +39,7 @@ class DefaultCubemapNormalNoSpecMaterial extends hxsl.Shader {
|
|||
}
|
||||
function vertex() {
|
||||
calculatedUV = input.uv;
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var pN = input.normal;
|
||||
// pN.x *= -1;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class DefaultDiffuseMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -28,7 +29,7 @@ class DefaultDiffuseMaterial extends hxsl.Shader {
|
|||
function vertex() {
|
||||
calculatedUV = input.uv;
|
||||
var objToTangentSpace = mat3(input.t, input.b, input.n);
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var n = input.normal;
|
||||
// n.x *= -1;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class DefaultMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -46,7 +47,7 @@ class DefaultMaterial extends hxsl.Shader {
|
|||
}
|
||||
var objToTangentSpace = mat3(input.t, input.b, input.n);
|
||||
outLightVec = vec4(0);
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var eyePos = camera.position * mat3x4(global.modelViewInverse);
|
||||
// eyePos.x *= -1;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class DefaultNormalMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -42,7 +43,7 @@ class DefaultNormalMaterial extends hxsl.Shader {
|
|||
function vertex() {
|
||||
calculatedUV = input.uv;
|
||||
outLightVec = vec4(0);
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var eyePos = camera.position * mat3x4(global.modelViewInverse);
|
||||
// eyePos.x *= -1;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class NoiseTileMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -42,7 +43,7 @@ class NoiseTileMaterial extends hxsl.Shader {
|
|||
calculatedUV = input.uv;
|
||||
var objToTangentSpace = mat3(input.t, input.b, input.n);
|
||||
outLightVec = vec4(0);
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var eyePos = camera.position * mat3x4(global.modelViewInverse);
|
||||
// eyePos.x *= -1;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class RefractMaterial extends hxsl.Shader {
|
|||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
var position:Vec3;
|
||||
|
|
@ -44,7 +45,7 @@ class RefractMaterial extends hxsl.Shader {
|
|||
calculatedUV = input.uv;
|
||||
var objToTangentSpace = mat3(input.t, input.b, input.n);
|
||||
outLightVec = vec4(0);
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * transposeMat3(mat3(global.modelView));
|
||||
var inLightVec = vec3(-0.5732, 0.27536, -0.77176) * mat3(global.modelViewTranspose);
|
||||
// inLightVec.x *= -1;
|
||||
var eyePos = camera.position * mat3x4(global.modelViewInverse);
|
||||
// eyePos.x *= -1;
|
||||
|
|
|
|||
155
src/shaders/RendererDefaultPass.hx
Normal file
155
src/shaders/RendererDefaultPass.hx
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package shaders;
|
||||
|
||||
import h3d.pass.PassObject;
|
||||
import h3d.pass.ShaderManager;
|
||||
import h3d.pass.Base;
|
||||
import h3d.pass.SortByMaterial;
|
||||
|
||||
@:build(hxsl.Macros.buildGlobals())
|
||||
@:access(h3d.mat.Pass)
|
||||
class RendererDefaultPass extends Base {
|
||||
var manager:ShaderManager;
|
||||
var globals(get, never):hxsl.Globals;
|
||||
var defaultSort = new SortByMaterial().sort;
|
||||
|
||||
inline function get_globals()
|
||||
return manager.globals;
|
||||
|
||||
@global("camera.view") var cameraView:h3d.Matrix = ctx.camera.mcam;
|
||||
@global("camera.zNear") var cameraNear:Float = ctx.camera.zNear;
|
||||
@global("camera.zFar") var cameraFar:Float = ctx.camera.zFar;
|
||||
@global("camera.proj") var cameraProj:h3d.Matrix = ctx.camera.mproj;
|
||||
@global("camera.position") var cameraPos:h3d.Vector = ctx.camera.pos;
|
||||
@global("camera.projDiag") var cameraProjDiag:h3d.Vector = new h3d.Vector(ctx.camera.mproj._11, ctx.camera.mproj._22, ctx.camera.mproj._33,
|
||||
ctx.camera.mproj._44);
|
||||
@global("camera.projFlip") var cameraProjFlip:Float = ctx.engine.driver.hasFeature(BottomLeftCoords)
|
||||
&& ctx.engine.getCurrentTarget() != null ? -1 : 1;
|
||||
@global("camera.viewProj") var cameraViewProj:h3d.Matrix = ctx.camera.m;
|
||||
@global("camera.inverseViewProj") var cameraInverseViewProj:h3d.Matrix = ctx.camera.getInverseViewProj();
|
||||
@global("global.time") var globalTime:Float = ctx.time;
|
||||
@global("global.pixelSize") var pixelSize:h3d.Vector = getCurrentPixelSize();
|
||||
@global("global.modelView") var globalModelView:h3d.Matrix;
|
||||
@global("global.modelViewInverse") var globalModelViewInverse:h3d.Matrix;
|
||||
@global("global.modelViewTranspose") var globalModelViewTranspose:h3d.Matrix;
|
||||
|
||||
public function new(name) {
|
||||
super(name);
|
||||
manager = new ShaderManager(getOutputs());
|
||||
initGlobals();
|
||||
}
|
||||
|
||||
function getCurrentPixelSize() {
|
||||
var t = ctx.engine.getCurrentTarget();
|
||||
return new h3d.Vector(2 / (t == null ? ctx.engine.width : t.width), 2 / (t == null ? ctx.engine.height : t.height));
|
||||
}
|
||||
|
||||
function getOutputs():Array<hxsl.Output> {
|
||||
return [Value("output.color")];
|
||||
}
|
||||
|
||||
override function compileShader(p:h3d.mat.Pass) {
|
||||
var o = @:privateAccess new h3d.pass.PassObject();
|
||||
o.pass = p;
|
||||
setupShaders(new h3d.pass.PassList(o));
|
||||
return manager.compileShaders(o.shaders, p.batchMode);
|
||||
}
|
||||
|
||||
function processShaders(p:h3d.pass.PassObject, shaders:hxsl.ShaderList) {
|
||||
var p = ctx.extraShaders;
|
||||
while (p != null) {
|
||||
shaders = ctx.allocShaderList(p.s, shaders);
|
||||
p = p.next;
|
||||
}
|
||||
return shaders;
|
||||
}
|
||||
|
||||
@:access(h3d.scene)
|
||||
function setupShaders(passes:h3d.pass.PassList) {
|
||||
var lightInit = false;
|
||||
for (p in passes) {
|
||||
var shaders = p.pass.getShadersRec();
|
||||
shaders = processShaders(p, shaders);
|
||||
if (p.pass.enableLights && ctx.lightSystem != null) {
|
||||
if (!lightInit) {
|
||||
ctx.lightSystem.initGlobals(globals);
|
||||
lightInit = true;
|
||||
}
|
||||
shaders = ctx.lightSystem.computeLight(p.obj, shaders);
|
||||
}
|
||||
p.shader = manager.compileShaders(shaders, p.pass.batchMode);
|
||||
p.shaders = shaders;
|
||||
var t = p.shader.fragment.textures;
|
||||
if (t == null || t.type.match(TArray(_)))
|
||||
p.texture = 0;
|
||||
else {
|
||||
var t:h3d.mat.Texture = manager.getParamValue(t, shaders, true);
|
||||
p.texture = t == null ? 0 : t.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline function log(str:String) {
|
||||
ctx.engine.driver.log(str);
|
||||
}
|
||||
|
||||
function drawObject(p:h3d.pass.PassObject) {
|
||||
ctx.drawPass = p;
|
||||
ctx.engine.selectMaterial(p.pass);
|
||||
@:privateAccess p.obj.draw(ctx);
|
||||
}
|
||||
|
||||
static public dynamic function onShaderError(e:Dynamic, p:PassObject) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@:access(h3d.scene)
|
||||
override function draw(passes:h3d.pass.PassList, ?sort:h3d.pass.PassList->Void) {
|
||||
if (passes.isEmpty())
|
||||
return;
|
||||
#if sceneprof h3d.impl.SceneProf.begin("draw", ctx.frame); #end
|
||||
for (g in ctx.sharedGlobals)
|
||||
globals.fastSet(g.gid, g.value);
|
||||
setGlobals();
|
||||
setupShaders(passes);
|
||||
if (sort == null)
|
||||
defaultSort(passes);
|
||||
else
|
||||
sort(passes);
|
||||
ctx.currentManager = manager;
|
||||
var buf = ctx.shaderBuffers, prevShader = null;
|
||||
for (p in passes) {
|
||||
#if sceneprof h3d.impl.SceneProf.mark(p.obj); #end
|
||||
globalModelView = p.obj.absPos;
|
||||
if (p.shader.hasGlobal(globalModelViewTranspose_id.toInt())) {
|
||||
globalModelViewTranspose = globalModelView.clone();
|
||||
globalModelViewTranspose.transpose();
|
||||
}
|
||||
if (p.shader.hasGlobal(globalModelViewInverse_id.toInt()))
|
||||
globalModelViewInverse = p.obj.getInvPos();
|
||||
if (prevShader != p.shader) {
|
||||
prevShader = p.shader;
|
||||
try {
|
||||
ctx.engine.selectShader(p.shader);
|
||||
} catch (e:Dynamic) {
|
||||
onShaderError(e, p);
|
||||
continue;
|
||||
}
|
||||
if (buf == null)
|
||||
buf = ctx.shaderBuffers = new h3d.shader.Buffers(p.shader);
|
||||
else
|
||||
buf.grow(p.shader);
|
||||
manager.fillGlobals(buf, p.shader);
|
||||
ctx.engine.uploadShaderBuffers(buf, Globals);
|
||||
}
|
||||
if (!p.pass.dynamicParameters) {
|
||||
manager.fillParams(buf, p.shader, p.shaders);
|
||||
ctx.engine.uploadShaderBuffers(buf, Params);
|
||||
ctx.engine.uploadShaderBuffers(buf, Textures);
|
||||
ctx.engine.uploadShaderBuffers(buf, Buffers);
|
||||
}
|
||||
drawObject(p);
|
||||
}
|
||||
#if sceneprof h3d.impl.SceneProf.end(); #end
|
||||
ctx.nextPass();
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ class ClassicGlass extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class ClassicGlassPureSphere extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class ClassicMarb extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class ClassicMarb2 extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class ClassicMarb3 extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class ClassicMetal extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class CrystalMarb extends hxsl.Shader {
|
|||
};
|
||||
@global var global:{
|
||||
@perObject var modelView:Mat4;
|
||||
@perObject var modelViewTranspose:Mat4;
|
||||
@perObject var modelViewInverse:Mat4;
|
||||
};
|
||||
@input var input:{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue