public M2RenderInstance AddInstance(int uuid, Vector3 position, Vector3 rotation, Vector3 scaling) { M2RenderInstance inst; // ReSharper disable once InconsistentlySynchronizedField if (mFullInstances.TryGetValue(uuid, out inst)) { ++inst.NumReferences; return(inst); } var instance = new M2RenderInstance(uuid, position, rotation, scaling, this); lock (mFullInstances) { mFullInstances.Add(uuid, instance); if (!WorldFrame.Instance.ActiveCamera.Contains(ref instance.BoundingBox)) { return(instance); } lock (mInstanceBufferLock) mVisibleInstances.Add(instance); return(instance); } }
public void RenderSingleInstance(M2RenderInstance instance) { if (mIsSyncLoaded == false) { if (!BeginSyncLoad()) { return; } } if (mSkipRendering) { return; } // TODO: We *really* need to get rid of this! if (IO.FileManager.Instance.Version == IO.FileDataVersion.Lichking) { mSingleRenderer.OnFrame_Old(this, instance); } else { mSingleRenderer.OnFrame(this, instance); } }
private void UpdateAnimations(M2RenderInstance instance) { var camera = WorldFrame.Instance.ActiveCamera; mAnimator.Update(new BillboardParameters { Forward = camera.Forward, Right = camera.Right, Up = camera.Up, InverseRotation = instance.InverseRotation }); if (mAnimator.GetBones(mAnimationMatrices)) { mAnimBuffer.UpdateData(mAnimationMatrices); } }
// TODO: Get rid of this public void OnFrame_Old(M2Renderer renderer, M2RenderInstance instance) { var animator = mAnimator ?? renderer.Animator; if (mAnimator != null) { UpdateAnimations(instance); } gMesh.UpdateIndexBuffer(renderer.IndexBuffer); gMesh.UpdateVertexBuffer(renderer.VertexBuffer); gPerDrawCallBuffer.UpdateData(new PerDrawCallBuffer { instanceMat = instance.InstanceMatrix, colorMod = instance.HighlightColor }); gMesh.Program.SetVertexConstantBuffer(1, mAnimBuffer ?? renderer.AnimBuffer); foreach (var pass in mModel.Passes) { if (!mModel.NeedsPerInstanceAnimation) { // Prevent double rendering since this model pass // was already processed by the batch renderer if (pass.BlendMode == 0 || pass.BlendMode == 1) { continue; } } var oldProgram = gMesh.Program; ShaderProgram newProgram; switch (pass.BlendMode) { case 0: newProgram = gNoBlendProgram; break; case 1: newProgram = gBlendTestProgram; break; default: switch (pass.Textures.Count) { case 2: newProgram = g2PassProgram; break; case 3: newProgram = g3PassProgram; break; default: newProgram = gBlendProgram; break; } break; } if (newProgram != oldProgram) { gMesh.Program = newProgram; gMesh.Program.Bind(); } var depthState = gDepthNoWriteState; if (pass.BlendMode == 0 || pass.BlendMode == 1) { depthState = gDepthWriteState; } gMesh.UpdateDepthState(depthState); var cullingDisabled = (pass.RenderFlag & 0x04) != 0; gMesh.UpdateRasterizerState(cullingDisabled ? gNoCullState : gCullState); gMesh.UpdateBlendState(BlendStates[pass.BlendMode]); var unlit = ((pass.RenderFlag & 0x01) != 0) ? 0.0f : 1.0f; var unfogged = ((pass.RenderFlag & 0x02) != 0) ? 0.0f : 1.0f; Matrix uvAnimMat; animator.GetUvAnimMatrix(pass.TexAnimIndex, out uvAnimMat); var color = animator.GetColorValue(pass.ColorAnimIndex); var alpha = animator.GetAlphaValue(pass.AlphaAnimIndex); color.W *= alpha; gPerPassBuffer.UpdateData(new PerModelPassBuffer() { uvAnimMatrix1 = uvAnimMat, modelPassParams = new Vector4(unlit, unfogged, 0.0f, 0.0f), animatedColor = color }); for (var i = 0; i < pass.Textures.Count && i < 3; ++i) { gMesh.Program.SetPixelTexture(i, pass.Textures[i]); } gMesh.StartVertex = 0; gMesh.StartIndex = pass.StartIndex; gMesh.IndexCount = pass.IndexCount; gMesh.Draw(); } }
public void OnFrame(M2Renderer renderer, M2RenderInstance instance) { var animator = mAnimator ?? renderer.Animator; if (mAnimator != null) { UpdateAnimations(instance); } gMesh.UpdateIndexBuffer(renderer.IndexBuffer); gMesh.UpdateVertexBuffer(renderer.VertexBuffer); gPerDrawCallBuffer.UpdateData(new PerDrawCallBuffer { instanceMat = instance.InstanceMatrix, colorMod = instance.HighlightColor }); gMesh.Program.SetVertexConstantBuffer(1, mAnimBuffer ?? renderer.AnimBuffer); foreach (var pass in mModel.Passes) { if (!mModel.NeedsPerInstanceAnimation) { // Prevent double rendering since this model pass // was already processed by the batch renderer if (pass.BlendMode == 0 || pass.BlendMode == 1) { continue; } } // TODO: Since this isn't choosing among static programs anymore, cache a different way (comparison func?) var ctx = WorldFrame.Instance.GraphicsContext; gCustomProgram.SetVertexShader(ctx.M2Shaders.GetVertexShader_Single(pass.VertexShaderType)); gCustomProgram.SetPixelShader(ctx.M2Shaders.GetPixelShader(pass.PixelShaderType)); gMesh.Program = gCustomProgram; gCustomProgram.Bind(); var depthState = gDepthNoWriteState; if (pass.BlendMode == 0 || pass.BlendMode == 1) { depthState = gDepthWriteState; } gMesh.UpdateDepthState(depthState); var cullingDisabled = (pass.RenderFlag & 0x04) != 0; gMesh.UpdateRasterizerState(cullingDisabled ? gNoCullState : gCullState); gMesh.UpdateBlendState(BlendStates[pass.BlendMode]); var unlit = ((pass.RenderFlag & 0x01) != 0) ? 0.0f : 1.0f; var unfogged = ((pass.RenderFlag & 0x02) != 0) ? 0.0f : 1.0f; var alphakey = (pass.BlendMode == 1) ? 1.0f : 0.0f; // These are per texture var alphaValues = new float[] { 1, 1, 1, 1 }; for (var i = 0; i < pass.OpCount; ++i) { alphaValues[i] = animator.GetAlphaValue(pass.AlphaAnimIndex + i); } var uvAnimMatrix1 = Matrix.Identity; var uvAnimMatrix2 = Matrix.Identity; var uvAnimMatrix3 = Matrix.Identity; var uvAnimMatrix4 = Matrix.Identity; animator.GetUvAnimMatrix(pass.TexAnimIndex + 0, out uvAnimMatrix1); if (pass.OpCount >= 2) { animator.GetUvAnimMatrix(pass.TexAnimIndex + 1, out uvAnimMatrix2); } if (pass.OpCount >= 3) { animator.GetUvAnimMatrix(pass.TexAnimIndex + 2, out uvAnimMatrix3); } if (pass.OpCount >= 4) { animator.GetUvAnimMatrix(pass.TexAnimIndex + 3, out uvAnimMatrix4); } gPerPassBuffer.UpdateData(new PerModelPassBuffer() { uvAnimMatrix1 = uvAnimMatrix1, uvAnimMatrix2 = uvAnimMatrix2, uvAnimMatrix3 = uvAnimMatrix3, uvAnimMatrix4 = uvAnimMatrix4, transparency = new Vector4(alphaValues[0], alphaValues[1], alphaValues[2], alphaValues[3]), modelPassParams = new Vector4(unlit, unfogged, alphakey, 0.0f), animatedColor = animator.GetColorValue(pass.ColorAnimIndex) }); for (var i = 0; i < pass.OpCount && i < 4; ++i) { switch (mModel.TextureInfos[pass.TextureIndices[i]].SamplerFlags) { case Graphics.Texture.SamplerFlagType.WrapBoth: gMesh.Program.SetPixelSampler(i, gSamplerWrapBoth); break; case Graphics.Texture.SamplerFlagType.WrapU: gMesh.Program.SetPixelSampler(i, gSamplerWrapU); break; case Graphics.Texture.SamplerFlagType.WrapV: gMesh.Program.SetPixelSampler(i, gSamplerWrapV); break; case Graphics.Texture.SamplerFlagType.ClampBoth: gMesh.Program.SetPixelSampler(i, gSamplerClampBoth); break; } gMesh.Program.SetPixelTexture(i, pass.Textures[i]); } gMesh.StartVertex = 0; gMesh.StartIndex = pass.StartIndex; gMesh.IndexCount = pass.IndexCount; gMesh.Draw(); } }
public M2RenderInstance AddInstance(int uuid, Vector3 position, Vector3 rotation, Vector3 scaling) { M2RenderInstance inst; // ReSharper disable once InconsistentlySynchronizedField if (mFullInstances.TryGetValue(uuid, out inst)) { ++inst.NumReferences; return inst; } var instance = new M2RenderInstance(uuid, position, rotation, scaling, this); lock (mFullInstances) { mFullInstances.Add(uuid, instance); if (!WorldFrame.Instance.ActiveCamera.Contains(ref instance.BoundingBox)) return instance; lock (mInstanceBufferLock) mVisibleInstances.Add(instance); return instance; } }