protected override void OnCopyTo(Resource r, Duality.Cloning.CloneProvider provider) { base.OnCopyTo(r, provider); DrawTechnique c = r as DrawTechnique; c.blendType = this.blendType; }
protected override void OnCopyDataTo(object target, ICloneOperation operation) { base.OnCopyDataTo(target, operation); DrawTechnique targetTechnique = target as DrawTechnique; if (this.compiled) { targetTechnique.Compile(); } }
protected void PrepareVerticesLightSmooth(ref VertexC1P3T4A4A1[] vertices, IDrawDevice device, float curAnimFrameFade, ColorRgba mainClr, Rect uvRect, Rect uvRectNext, DrawTechnique tech) { bool perPixel = tech is LightingTechnique; Vector3 pos = this.GameObj.Transform.Pos; Vector3 posTemp = pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; float rotation = this.GameObj.Transform.Angle; MathF.GetTransformDotVec(rotation, out xDot, out yDot); Rect rectTemp = this.rect.Transformed(this.GameObj.Transform.Scale, this.GameObj.Transform.Scale); Vector2 edge1 = rectTemp.TopLeft; Vector2 edge2 = rectTemp.BottomLeft; Vector2 edge3 = rectTemp.BottomRight; Vector2 edge4 = rectTemp.TopRight; MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); MathF.TransformDotVec(ref edge2, ref xDot, ref yDot); MathF.TransformDotVec(ref edge3, ref xDot, ref yDot); MathF.TransformDotVec(ref edge4, ref xDot, ref yDot); // Using Per-Vertex Lighting? Calculate vertex light values Vector4[] vertexLight = null; if (!perPixel) { vertexLight = new Vector4[4]; Light.GetLightAtWorldPos(pos + new Vector3(edge1), out vertexLight[0], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge2), out vertexLight[1], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge3), out vertexLight[2], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge4), out vertexLight[3], this.vertexTranslucency); } Vector2.Multiply(ref edge1, scaleTemp, out edge1); Vector2.Multiply(ref edge2, scaleTemp, out edge2); Vector2.Multiply(ref edge3, scaleTemp, out edge3); Vector2.Multiply(ref edge4, scaleTemp, out edge4); // Using Per-Pixel Lighting? Pass objRotation Matrix via vertex attribute. Vector4 objRotMat = Vector4.Zero; if (perPixel) objRotMat = new Vector4((float)Math.Cos(-rotation), -(float)Math.Sin(-rotation), (float)Math.Sin(-rotation), (float)Math.Cos(-rotation)); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T4A4A1[4]; // Calculate UV coordinates float left = uvRect.X; float right = uvRect.RightX; float top = uvRect.Y; float bottom = uvRect.BottomY; float nextLeft = uvRectNext.X; float nextRight = uvRectNext.RightX; float nextTop = uvRectNext.Y; float nextBottom = uvRectNext.BottomY; if ((this.flipMode & FlipMode.Horizontal) != FlipMode.None) { MathF.Swap(ref left, ref right); MathF.Swap(ref nextLeft, ref nextRight); } if ((this.flipMode & FlipMode.Vertical) != FlipMode.None) { MathF.Swap(ref top, ref bottom); MathF.Swap(ref nextTop, ref nextBottom); } // Directly pass World Position with each vertex, see note in Light.cs vertices[0].Pos.X = posTemp.X + edge1.X; vertices[0].Pos.Y = posTemp.Y + edge1.Y; vertices[0].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[0].TexCoord.X = left; vertices[0].TexCoord.Y = top; vertices[0].TexCoord.Z = nextLeft; vertices[0].TexCoord.W = nextTop; vertices[0].Color = mainClr; vertices[0].Attrib = perPixel ? objRotMat : vertexLight[0]; vertices[0].Attrib2 = curAnimFrameFade; vertices[1].Pos.X = posTemp.X + edge2.X; vertices[1].Pos.Y = posTemp.Y + edge2.Y; vertices[1].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[1].TexCoord.X = left; vertices[1].TexCoord.Y = bottom; vertices[1].TexCoord.Z = nextLeft; vertices[1].TexCoord.W = nextBottom; vertices[1].Color = mainClr; vertices[1].Attrib = perPixel ? objRotMat : vertexLight[1]; vertices[1].Attrib2 = curAnimFrameFade; vertices[2].Pos.X = posTemp.X + edge3.X; vertices[2].Pos.Y = posTemp.Y + edge3.Y; vertices[2].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[2].TexCoord.X = right; vertices[2].TexCoord.Y = bottom; vertices[2].TexCoord.Z = nextRight; vertices[2].TexCoord.W = nextBottom; vertices[2].Color = mainClr; vertices[2].Attrib = perPixel ? objRotMat : vertexLight[2]; vertices[2].Attrib2 = curAnimFrameFade; vertices[3].Pos.X = posTemp.X + edge4.X; vertices[3].Pos.Y = posTemp.Y + edge4.Y; vertices[3].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[3].TexCoord.X = right; vertices[3].TexCoord.Y = top; vertices[3].TexCoord.Z = nextRight; vertices[3].TexCoord.W = nextTop; vertices[3].Color = mainClr; vertices[3].Attrib = perPixel ? objRotMat : vertexLight[3]; vertices[3].Attrib2 = curAnimFrameFade; if (this.pixelGrid) { vertices[0].Pos.X = MathF.Round(vertices[0].Pos.X); vertices[1].Pos.X = MathF.Round(vertices[1].Pos.X); vertices[2].Pos.X = MathF.Round(vertices[2].Pos.X); vertices[3].Pos.X = MathF.Round(vertices[3].Pos.X); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { vertices[0].Pos.X += 0.5f; vertices[1].Pos.X += 0.5f; vertices[2].Pos.X += 0.5f; vertices[3].Pos.X += 0.5f; } vertices[0].Pos.Y = MathF.Round(vertices[0].Pos.Y); vertices[1].Pos.Y = MathF.Round(vertices[1].Pos.Y); vertices[2].Pos.Y = MathF.Round(vertices[2].Pos.Y); vertices[3].Pos.Y = MathF.Round(vertices[3].Pos.Y); if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { vertices[0].Pos.Y += 0.5f; vertices[1].Pos.Y += 0.5f; vertices[2].Pos.Y += 0.5f; vertices[3].Pos.Y += 0.5f; } } }
protected void PrepareVerticesLight(ref VertexC1P3T2A4[] vertices, IDrawDevice device, ColorRgba mainClr, Rect uvRect, DrawTechnique tech) { bool perPixel = tech is LightingTechnique; Vector3 pos = this.GameObj.Transform.Pos; Vector3 posTemp = pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; float rotation = this.GameObj.Transform.Angle; MathF.GetTransformDotVec(rotation, out xDot, out yDot); Rect rectTemp = this.rect.Transform(this.GameObj.Transform.Scale, this.GameObj.Transform.Scale); Vector2 edge1 = rectTemp.TopLeft; Vector2 edge2 = rectTemp.BottomLeft; Vector2 edge3 = rectTemp.BottomRight; Vector2 edge4 = rectTemp.TopRight; MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); MathF.TransformDotVec(ref edge2, ref xDot, ref yDot); MathF.TransformDotVec(ref edge3, ref xDot, ref yDot); MathF.TransformDotVec(ref edge4, ref xDot, ref yDot); // Using Per-Vertex Lighting? Calculate vertex light values Vector4[] vertexLight = null; if (!perPixel) { vertexLight = new Vector4[4]; Light.GetLightAtWorldPos(pos + new Vector3(edge1), out vertexLight[0], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge2), out vertexLight[1], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge3), out vertexLight[2], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge4), out vertexLight[3], this.vertexTranslucency); } Vector2.Multiply(ref edge1, scaleTemp, out edge1); Vector2.Multiply(ref edge2, scaleTemp, out edge2); Vector2.Multiply(ref edge3, scaleTemp, out edge3); Vector2.Multiply(ref edge4, scaleTemp, out edge4); // Using Per-Pixel Lighting? Pass objRotation Matrix via vertex attribute. Vector4 objRotMat = Vector4.Zero; if (perPixel) objRotMat = new Vector4((float)Math.Cos(-rotation), -(float)Math.Sin(-rotation), (float)Math.Sin(-rotation), (float)Math.Cos(-rotation)); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T2A4[4]; vertices[0].Pos.X = posTemp.X + edge1.X; vertices[0].Pos.Y = posTemp.Y + edge1.Y; vertices[0].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[0].TexCoord.X = uvRect.X; vertices[0].TexCoord.Y = uvRect.Y; vertices[0].Color = mainClr; vertices[0].Attrib = perPixel ? objRotMat : vertexLight[0]; vertices[1].Pos.X = posTemp.X + edge2.X; vertices[1].Pos.Y = posTemp.Y + edge2.Y; vertices[1].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[1].TexCoord.X = uvRect.X; vertices[1].TexCoord.Y = uvRect.MaximumY; vertices[1].Color = mainClr; vertices[1].Attrib = perPixel ? objRotMat : vertexLight[1]; vertices[2].Pos.X = posTemp.X + edge3.X; vertices[2].Pos.Y = posTemp.Y + edge3.Y; vertices[2].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[2].TexCoord.X = uvRect.MaximumX; vertices[2].TexCoord.Y = uvRect.MaximumY; vertices[2].Color = mainClr; vertices[2].Attrib = perPixel ? objRotMat : vertexLight[2]; vertices[3].Pos.X = posTemp.X + edge4.X; vertices[3].Pos.Y = posTemp.Y + edge4.Y; vertices[3].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[3].TexCoord.X = uvRect.MaximumX; vertices[3].TexCoord.Y = uvRect.Y; vertices[3].Color = mainClr; vertices[3].Attrib = perPixel ? objRotMat : vertexLight[3]; }
/// <summary> /// Sets up the appropriate OpenGL rendering state for this DrawTechnique. /// </summary> /// <param name="lastTechnique">The last DrawTechnique that has been set up. This parameter is optional, but /// specifying it will increase performance by reducing redundant state changes.</param> /// <param name="textures">A set of <see cref="Duality.Resources.Texture">Textures</see> to use.</param> /// <param name="uniforms">A set of <see cref="Duality.Resources.ShaderVarInfo">uniform values</see> to apply.</param> public void SetupForRendering(IDrawDevice device, BatchInfo material, DrawTechnique lastTechnique) { // Prepare Rendering if (this.NeedsPreparation) { // Clone the material, if not done yet due to vertex preprocessing if (!this.NeedsPreprocess) { material = new BatchInfo(material); } this.PrepareRendering(device, material); } // Setup BlendType if (lastTechnique == null || this.blendType != lastTechnique.blendType) { this.SetupBlendType(this.blendType, device.DepthWrite); } // Bind Shader ContentRef <ShaderProgram> selShader = this.SelectShader(); if (lastTechnique == null || selShader.Res != lastTechnique.shader.Res) { ShaderProgram.Bind(selShader); } // Setup shader data if (selShader.IsAvailable) { ShaderVarInfo[] varInfo = selShader.Res.VarInfo; // Setup sampler bindings automatically int curSamplerIndex = 0; if (material.Textures != null) { for (int i = 0; i < varInfo.Length; i++) { if (varInfo[i].glVarLoc == -1) { continue; } if (varInfo[i].type != ShaderVarType.Sampler2D) { continue; } // Bind Texture ContentRef <Texture> texRef = material.GetTexture(varInfo[i].name); Texture.Bind(texRef, curSamplerIndex); GL.Uniform1(varInfo[i].glVarLoc, curSamplerIndex); curSamplerIndex++; } } Texture.ResetBinding(curSamplerIndex); // Transfer uniform data from material to actual shader if (material.Uniforms != null) { for (int i = 0; i < varInfo.Length; i++) { if (varInfo[i].glVarLoc == -1) { continue; } float[] data = material.GetUniform(varInfo[i].name); if (data == null) { continue; } varInfo[i].SetupUniform(data); } } } // Setup fixed function data else { // Fixed function texture binding if (material.Textures != null) { int samplerIndex = 0; foreach (var pair in material.Textures) { Texture.Bind(pair.Value, samplerIndex); samplerIndex++; } Texture.ResetBinding(samplerIndex); } else { Texture.ResetBinding(); } } }
protected void GetAnimData(Texture mainTex, DrawTechnique tech, bool smoothShaderInput, out Rect uvRect, out Rect uvRectNext) { this.UpdateVisibleFrames(); if (mainTex != null) { mainTex.LookupAtlas(this.curAnimFrame, out uvRect); if (smoothShaderInput) mainTex.LookupAtlas(this.nextAnimFrame, out uvRectNext); else uvRectNext = uvRect; } else if (mainTex != null) uvRect = uvRectNext = new Rect(mainTex.UVRatio.X, mainTex.UVRatio.Y); else uvRect = uvRectNext = new Rect(1.0f, 1.0f); }