/// <summary> /// /// </summary> /// <param name="c"></param> /// <param name="dobj"></param> /// <param name="parentJOBJ"></param> /// <param name="jobjManager"></param> public void RenderDOBJShader(Camera camera, HSD_DOBJ dobj, HSD_JOBJ parentJOBJ, JOBJManager jobjManager, bool selected = false) { if (dobj.Pobj == null) return; if (HiddenDOBJs.Contains(dobj) || (selected && OnlyRenderSelected)) return; if (OnlyRenderSelected && SelectedDOBJ != null && SelectedDOBJ._s != dobj._s) return; var mobj = dobj.Mobj; var pobjs = dobj.Pobj.List; if(!DOBJtoBuffer.ContainsKey(dobj)) LoadDOBJ(dobj, jobjManager); if (!DOBJtoBuffer.ContainsKey(dobj)) return; if (GXShader == null) { GXShader = new Shader(); GXShader.LoadShader(@"Shader\gx.vert"); GXShader.LoadShader(@"Shader\gx.frag"); } GL.UseProgram(GXShader.programId); var mvp = camera.MvpMatrix; GL.UniformMatrix4(GXShader.GetVertexAttributeUniformLocation("mvp"), false, ref mvp); Vector3 camPos = (camera.RotationMatrix * new Vector4(camera.Translation, 1)).Xyz; GXShader.SetVector3("cameraPos", camPos); Matrix4 single = Matrix4.Identity; if (parentJOBJ != null && jobjManager != null) single = jobjManager.GetWorldTransform(parentJOBJ); GL.UniformMatrix4(GXShader.GetVertexAttributeUniformLocation("singleBind"), false, ref single); var rootJOBJ = jobjManager.GetJOBJ(0); GXShader.SetBoolToInt("isRootBound", parentJOBJ?._s == rootJOBJ?._s); GXShader.SetWorldTransformBones(jobjManager.GetWorldTransforms()); //GXShader.SetBindTransformBones(jobjManager.GetBindTransforms()); var tb = jobjManager.GetBindTransforms(); if (tb.Length > 0) GXShader.SetMatrix4x4("binds", tb); GL.Uniform3(GXShader.GetVertexAttributeUniformLocation("overlayColor"), OverlayColor); Matrix4 sphereMatrix = camera.ModelViewMatrix; sphereMatrix.Invert(); sphereMatrix.Transpose(); GXShader.SetMatrix4x4("sphereMatrix", ref sphereMatrix); float wscale = 1; float hscale = 1; bool mirrorX = false; bool mirrorY = false; if (mobj != null) BindMOBJ(GXShader, mobj, out wscale, out hscale, out mirrorX, out mirrorY); GL.BindBuffer(BufferTarget.ArrayBuffer, DOBJtoBuffer[dobj]); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX"), 1, VertexAttribPointerType.Short, false, GX_Vertex.Stride, 0); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 8); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 20); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_CLR0")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_CLR0"), 4, VertexAttribPointerType.Float, true, GX_Vertex.Stride, 56); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0"), 2, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 88); if (selected) { GL.Uniform1(GXShader.GetVertexAttributeUniformLocation("colorOverride"), 1); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } else { GL.PolygonMode(MaterialFace.Back, PolygonMode.Fill); GL.Uniform1(GXShader.GetVertexAttributeUniformLocation("colorOverride"), 0); } foreach (var p in DOBJtoPOBJCache[dobj]) { var en = p.Envelopes; GL.Uniform4(GXShader.GetVertexAttributeUniformLocation("envelopeIndex"), p.Envelopes.Length, ref p.Envelopes[0].X); var we = p.Weights; GL.Uniform4(GXShader.GetVertexAttributeUniformLocation("weights"), p.Weights.Length, ref p.Weights[0].X); GL.Uniform1(GXShader.GetVertexAttributeUniformLocation("hasEnvelopes"), p.HasWeighting ? 1 : 0); foreach (var dl in p.DisplayLists) GL.DrawArrays(dl.PrimType, dl.Offset, dl.Count); } GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX")); GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS")); GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM")); GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0")); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.UseProgram(0); }
/// <summary> /// Prepares DOBJ for rendering by loading relevant information into a cache /// </summary> private void LoadDOBJ(HSD_DOBJ dobj, JOBJManager jobjManager) { if(DOBJtoBuffer.ContainsKey(dobj)) { GL.DeleteBuffer(DOBJtoBuffer[dobj]); DOBJtoBuffer.Remove(dobj); } List<CachedPOBJ> pobjs = new List<CachedPOBJ>(); List<GX_Vertex> vertices = new List<GX_Vertex>(); int off = 0; foreach(var pobj in dobj.Pobj.List) { var dl = pobj.ToDisplayList(); vertices.AddRange(dl.Vertices); var pobjCache = new CachedPOBJ(); // build envelopes int eni = 0; foreach(var v in dl.Envelopes) { Vector4 b = new Vector4(); Vector4 w = new Vector4(); for(int i = 0; i < v.EnvelopeCount; i++) { if (i >= 4) break; w[i] = v.GetWeightAt(i); b[i] = jobjManager.IndexOf(v.GetJOBJAt(i)); } pobjCache.Weights[eni] = w; pobjCache.Envelopes[eni] = b; eni++; pobjCache.HasWeighting = v.EnvelopeCount > 0; } // load display list foreach (var v in dl.Primitives) { pobjCache.DisplayLists.Add(new CachedDL() { Offset = off, Count = v.Count, PrimType = GXTranslator.toPrimitiveType(v.PrimitiveType) }); off += v.Count; } pobjs.Add(pobjCache); } var arr = vertices.ToArray(); int buf; GL.GenBuffers(1, out buf); GL.BindBuffer(BufferTarget.ArrayBuffer, buf); GL.BufferData(BufferTarget.ArrayBuffer, arr.Length * GX_Vertex.Stride, arr, BufferUsageHint.StaticDraw); DOBJtoBuffer.Add(dobj, buf); DOBJtoPOBJCache.Add(dobj, pobjs); }