/// <summary> /// 遍历以<paramref name="lastVertexId"/>为最后一个顶点的图元, /// 瞄准每个图元的索引(例如1个三角形有3个索引)中的最后一个索引, /// 将此索引在<see cref="IndexBuffer"/>中的索引(位置)收集起来。 /// </summary> /// <param name="arg"></param> /// <param name="lastVertexId"></param> /// <returns></returns> private List <RecognizedPrimitiveInfo> GetLastIndexIdList(RenderEventArgs arg, uint lastVertexId) { PrimitiveRecognizer recognizer = PrimitiveRecognizerFactory.Create( (arg.PickingGeometryType == PickingGeometryType.Point && this.indexBuffer.Mode.ToGeometryType() == PickingGeometryType.Line) ? DrawMode.Points : this.indexBuffer.Mode); PrimitiveRestartState glState = GetPrimitiveRestartState(); var buffer = this.indexBuffer as OneIndexBuffer; IntPtr pointer = buffer.MapBuffer(MapBufferAccess.ReadOnly); List <RecognizedPrimitiveInfo> primitiveInfoList = null; if (glState == null) { primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, this.indexBuffer as OneIndexBuffer); } else { primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, this.indexBuffer as OneIndexBuffer, glState.RestartIndex); } buffer.UnmapBuffer(); return(primitiveInfoList); }
/// <summary> /// 遍历以<paramref name="lastVertexId"/>为最后一个顶点的图元, /// 瞄准每个图元的索引(例如1个三角形有3个索引)中的最后一个索引, /// 将此索引在<see cref="IndexBuffer"/>中的索引(位置)收集起来。 /// </summary> /// <param name="arg"></param> /// <param name="lastVertexId"></param> /// <returns></returns> private List <RecognizedPrimitiveInfo> GetLastIndexIdList(PickingEventArgs arg, uint lastVertexId) { var indexBuffer = this.Renderer.PickingRenderUnit.VertexArrayObject.IndexBuffer; PrimitiveRecognizer recognizer = PrimitiveRecognizerFactory.Create( (arg.GeometryType.Contains(GeometryType.Point) && indexBuffer.Mode.ToGeometryType() == GeometryType.Line) ? DrawMode.Points : indexBuffer.Mode); PrimitiveRestartState glState = GetPrimitiveRestartState(); var buffer = indexBuffer as OneIndexBuffer; IntPtr pointer = buffer.MapBuffer(MapBufferAccess.ReadOnly); List <RecognizedPrimitiveInfo> primitiveInfoList = null; if (glState == null) { primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, indexBuffer as OneIndexBuffer); } else { primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, indexBuffer as OneIndexBuffer, glState.RestartIndex); } buffer.UnmapBuffer(); return(primitiveInfoList); }
/// <summary> /// 遍历以<paramref name="lastVertexId"/>为最后一个顶点的图元, /// 瞄准每个图元的索引(例如1个三角形有3个索引)中的最后一个索引, /// 将此索引在<see cref="IndexBuffer"/>中的索引(位置)收集起来。 /// </summary> /// <param name="arg"></param> /// <param name="lastVertexId"></param> /// <returns></returns> private List <RecognizedPrimitiveInfo> GetLastIndexIdList(PickingEventArgs arg, uint lastVertexId) { var drawCmd = this.DrawCommand; PrimitiveRecognizer recognizer = PrimitiveRecognizerFactory.Create( (arg.GeometryType.Contains(GeometryType.Point) && drawCmd.Mode.ToGeometryType() == GeometryType.Line) ? DrawMode.Points : drawCmd.Mode); PrimitiveRestartState glState = GetPrimitiveRestartState(); var buffer = (drawCmd as IHasIndexBuffer).IndexBufferObject; IntPtr pointer = buffer.MapBuffer(MapBufferAccess.ReadOnly); List <RecognizedPrimitiveInfo> primitiveInfoList = null; if (glState == null) { primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, drawCmd as DrawElementsCmd); } else { primitiveInfoList = recognizer.Recognize(lastVertexId, pointer, drawCmd as DrawElementsCmd, glState.RestartIndex); } buffer.UnmapBuffer(); return(primitiveInfoList); }
private PrimitiveRestartState GetPrimitiveRestartState(OneIndexBuffer indexBuffer) { PrimitiveRestartState result = null; switch (indexBuffer.ElementType) { case IndexBufferElementType.UByte: if (this.ubyteRestartIndexState == null) { this.ubyteRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.ubyteRestartIndexState; break; case IndexBufferElementType.UShort: if (this.ushortRestartIndexState == null) { this.ushortRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.ushortRestartIndexState; break; case IndexBufferElementType.UInt: if (this.uintRestartIndexState == null) { this.uintRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.uintRestartIndexState; break; default: throw new NotImplementedException(); } return result; }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public IPickableRenderUnit ToRenderUnit(IBufferSource model) { // init shader program. ShaderProgram pickProgram = this.programProvider.GetShaderProgram(); // init vertex attribute buffer objects. VertexBuffer positionBuffer = model.GetVertexAttributeBuffer(this.positionNameInIBufferSource); // RULE: 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (positionBuffer == null || positionBuffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // init VAO. var pickingVAO = new VertexArrayObject(indexBuffer, pickProgram, new VertexShaderAttribute(positionBuffer, PickingShaderHelper.in_Position)); var renderUnit = new IPickableRenderUnit(pickProgram, pickingVAO, positionBuffer, this.states); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); renderUnit.StateList.Add(glState); } return(renderUnit); }
/// <summary> /// /// </summary> protected override void DoInitialize() { // init shader program. ShaderProgram program = this.shaderCodes.CreateProgram(); // init property buffer objects. VertexBuffer positionBuffer = null; IBufferable model = this.DataSource; VertexBuffer[] vertexAttributeBuffers; { var list = new List <VertexBuffer>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } if (item.NameInIBufferable == positionNameInIBufferable) { if (positionBuffer != null) { throw new Exception(string.Format("Duplicate position buffer is not allowed!")); } positionBuffer = buffer.Clone() as VertexBuffer; positionBuffer.VarNameInVertexShader = "in_Position";// in_Postion same with in the PickingShader.vert shader } list.Add(buffer); } vertexAttributeBuffers = list.ToArray(); } // init index buffer OneIndexBuffer indexBuffer; { var mode = DrawMode.Points;//any mode is OK as we'll update it later in other place. indexBuffer = Buffer.Create(IndexBufferElementType.UInt, positionBuffer.ByteLength / (positionBuffer.Config.GetDataSize() * positionBuffer.Config.GetDataTypeByteLength()), mode, BufferUsage.StaticDraw); this.maxElementCount = indexBuffer.ElementCount; indexBuffer.ElementCount = 0;// 高亮0个图元 // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. GLState glState = new PrimitiveRestartState(indexBuffer.ElementType); this.stateList.Add(glState); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, vertexAttributeBuffers); vertexArrayObject.Initialize(program); // sets fields. this.Program = program; this.vertexAttributeBuffers = vertexAttributeBuffers; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; this.positionBuffer = positionBuffer; }
protected override void DoInitialize() { // init shader program. ShaderProgram program = this.shaderCodes.CreateProgram(); VertexBuffer positionBuffer = null; IBufferable model = this.DataSource; VertexBuffer[] vertexAttributeBuffers; { var list = new List <VertexBuffer>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } if (item.NameInIBufferable == this.PositionNameInIBufferable) { positionBuffer = buffer.Clone() as VertexBuffer; positionBuffer.VarNameInVertexShader = "in_Position";// in_Postion same with in the PickingShader.vert shader break; } list.Add(buffer); } vertexAttributeBuffers = list.ToArray(); } // 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (positionBuffer == null || positionBuffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); this.stateList.Add(glState); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, positionBuffer); vertexArrayObject.Initialize(program); // sets fields. this.Program = program; this.vertexAttributeBuffers = new VertexBuffer[] { positionBuffer }; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; }
private void RenderForPicking(PickingEventArgs arg, ControlMode controlMode, IDrawCommand tmpCmd) { if (!this.IsInitialized) { this.Initialize(); } this.polygonModeState.Mode = arg.GeometryType.GetPolygonMode(); ShaderProgram program = this.PickingRenderUnit.Program; // 绑定shader program.Bind(); { mat4 projection = arg.Scene.Camera.GetProjectionMatrix(); mat4 view = arg.Scene.Camera.GetViewMatrix(); mat4 model = this.GetModelMatrix(); program.glUniform("MVP", projection * view * model); } this.polygonModeState.On(); this.lineWidthState.On(); this.pointSizeState.On(); PrimitiveRestartState restart = null; var hasIndexBuffer = tmpCmd as IHasIndexBuffer; if (hasIndexBuffer != null) { restart = this.GetPrimitiveRestartState(hasIndexBuffer.IndexBufferObject.ElementType); } if (restart != null) { restart.On(); } { var pickable = this as IPickable; uint baseId = pickable.PickingBaseId; foreach (var vao in this.PickingRenderUnit.VertexArrayObjects) { program.glUniform("pickingBaseId", (int)(baseId)); vao.Draw(controlMode, tmpCmd); baseId += (uint)vao.VertexAttributes[0].Buffer.Length; } } if (restart != null) { restart.Off(); } this.pointSizeState.Off(); this.lineWidthState.Off(); this.polygonModeState.Off(); // 解绑shader program.Unbind(); }
/// <summary> /// /// </summary> protected override void DoInitialize() { // init shader program. ShaderProgram program = this.shaderCodes.CreateProgram(); // init property buffer objects. VertexBuffer positionBuffer = null; IBufferable model = this.DataSource; VertexBuffer[] vertexAttributeBuffers; { var list = new List<VertexBuffer>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } if (item.NameInIBufferable == positionNameInIBufferable) { if (positionBuffer != null) { throw new Exception(string.Format("Duplicate position buffer is not allowed!")); } positionBuffer = buffer.Clone() as VertexBuffer; positionBuffer.VarNameInVertexShader = "in_Position";// in_Postion same with in the PickingShader.vert shader } list.Add(buffer); } vertexAttributeBuffers = list.ToArray(); } // init index buffer OneIndexBuffer indexBuffer; { var mode = DrawMode.Points;//any mode is OK as we'll update it later in other place. indexBuffer = Buffer.Create(IndexBufferElementType.UInt, positionBuffer.ByteLength / (positionBuffer.Config.GetDataSize() * positionBuffer.Config.GetDataTypeByteLength()), mode, BufferUsage.StaticDraw); this.maxElementCount = indexBuffer.ElementCount; indexBuffer.ElementCount = 0;// 高亮0个图元 // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. GLState glState = new PrimitiveRestartState(indexBuffer.ElementType); this.stateList.Add(glState); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, vertexAttributeBuffers); vertexArrayObject.Initialize(program); // sets fields. this.Program = program; this.vertexAttributeBuffers = vertexAttributeBuffers; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; this.positionBuffer = positionBuffer; }
protected override void DoInitialize() { // init shader program. ShaderProgram program = this.shaderCodes.CreateProgram(); VertexBuffer positionBuffer = null; IBufferable model = this.DataSource; VertexBuffer[] vertexAttributeBuffers; { var list = new List<VertexBuffer>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } if (item.NameInIBufferable == this.PositionNameInIBufferable) { positionBuffer = buffer.Clone() as VertexBuffer; positionBuffer.VarNameInVertexShader = "in_Position";// in_Postion same with in the PickingShader.vert shader break; } list.Add(buffer); } vertexAttributeBuffers = list.ToArray(); } // 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (positionBuffer == null || positionBuffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); this.stateList.Add(glState); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, positionBuffer); vertexArrayObject.Initialize(program); // sets fields. this.Program = program; this.vertexAttributeBuffers = new VertexBuffer[] { positionBuffer }; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; }
/// <summary> /// /// </summary> protected override void DoInitialize() { // init shader program. ShaderProgram program = this.shaderCodes.CreateProgram(); // init vertex attribute buffer objects. IBufferable model = this.DataSource; VertexBuffer[] vertexAttributeBuffers; { var list = new List <VertexBuffer>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } list.Add(buffer); } vertexAttributeBuffers = list.ToArray(); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); this.stateList.Add(glState); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, vertexAttributeBuffers); vertexArrayObject.Initialize(program); // sets fields. this.Program = program; this.vertexAttributeBuffers = vertexAttributeBuffers; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; }
private void RenderForPicking(PickingEventArgs arg, IndexBuffer tempIndexBuffer) { if (!this.IsInitialized) { this.Initialize(); } this.polygonModeState.Mode = arg.GeometryType.GetPolygonMode(); ShaderProgram program = this.PickingRenderUnit.Program; // 绑定shader program.Bind(); program.glUniform("pickingBaseId", (int)(((IPickable)this).PickingBaseId)); { mat4 projection = arg.Scene.Camera.GetProjectionMatrix(); mat4 view = arg.Scene.Camera.GetViewMatrix(); mat4 model = this.GetModelMatrix(); program.glUniform("MVP", projection * view * model); } this.polygonModeState.On(); this.lineWidthState.On(); this.pointSizeState.On(); var oneIndexBuffer = tempIndexBuffer as OneIndexBuffer; if (oneIndexBuffer != null) { PrimitiveRestartState glState = this.GetPrimitiveRestartState(oneIndexBuffer); glState.On(); this.PickingRenderUnit.VertexArrayObject.Draw(this.ControlMode, tempIndexBuffer); glState.Off(); } else { this.PickingRenderUnit.VertexArrayObject.Draw(this.ControlMode, tempIndexBuffer); } this.pointSizeState.Off(); this.lineWidthState.Off(); this.polygonModeState.Off(); // 解绑shader program.Unbind(); }
private void NoPrimitiveRestartIndex(List <RecognizedPrimitiveInfo> primitiveInfoList) { PrimitiveRestartState glState = GetPrimitiveRestartState(); if (glState != null) { foreach (RecognizedPrimitiveInfo info in primitiveInfoList) { foreach (uint vertexId in info.VertexIds) { if (vertexId == glState.RestartIndex) { throw new Exception(); } } } } }
/// <summary> /// /// </summary> protected override void DoInitialize() { // init shader program. ShaderProgram program = this.shaderCodes.CreateProgram(); // init vertex attribute buffer objects. IBufferable model = this.DataSource; VertexBuffer[] vertexAttributeBuffers; { var list = new List<VertexBuffer>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } list.Add(buffer); } vertexAttributeBuffers = list.ToArray(); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); this.stateList.Add(glState); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, vertexAttributeBuffers); vertexArrayObject.Initialize(program); // sets fields. this.Program = program; this.vertexAttributeBuffers = vertexAttributeBuffers; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; }
/// <summary> /// render with specified index buffer. /// </summary> /// <param name="arg"></param> /// <param name="temporaryIndexBuffer"></param> private void Render4Picking(RenderEventArgs arg, IndexBuffer temporaryIndexBuffer) { UpdatePolygonMode(arg.PickingGeometryType); ShaderProgram program = this.Program; // 绑定shader program.Bind(); program.glUniform("pickingBaseId", 0); UniformMat4 uniformmMVP4Picking = this.uniformmMVP4Picking; { mat4 projection = arg.Camera.GetProjectionMatrix(); mat4 view = arg.Camera.GetViewMatrix(); mat4 model = this.GetModelMatrix().Value; uniformmMVP4Picking.Value = projection * view * model; } uniformmMVP4Picking.SetUniform(program); PickingStateesOn(); var oneIndexBuffer = temporaryIndexBuffer as OneIndexBuffer; if (oneIndexBuffer != null) { PrimitiveRestartState glState = this.GetPrimitiveRestartState(oneIndexBuffer); glState.On(); this.vertexArrayObject.Render(arg, program, temporaryIndexBuffer); glState.Off(); } else { this.vertexArrayObject.Render(arg, program, temporaryIndexBuffer); } PickingStateesOff(); //if (mvpUpdated) { uniformmMVP4Picking.ResetUniform(program); } // 解绑shader program.Unbind(); }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public RenderUnit ToRenderUnit(IBufferSource model) { // init shader program. ShaderProgram program = this.programProvider.GetShaderProgram(); // init vertex attribute buffer objects. VertexShaderAttribute[] vertexAttributeBuffers; { var list = new List <VertexShaderAttribute>(); foreach (AttributeMap.NamePair item in this.map) { VertexBuffer buffer = model.GetVertexAttributeBuffer(item.NameInIBufferSource); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } list.Add(new VertexShaderAttribute(buffer, item.VarNameInShader)); } vertexAttributeBuffers = list.ToArray(); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, program, vertexAttributeBuffers); var result = new RenderUnit(program, vertexArrayObject, this.states); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care of this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); result.StateList.Add(glState); } return(result); }
private PrimitiveRestartState GetPrimitiveRestartState(OneIndexBuffer indexBuffer) { PrimitiveRestartState result = null; switch (indexBuffer.ElementType) { case IndexBufferElementType.UByte: if (this.ubyteRestartIndexState == null) { this.ubyteRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.ubyteRestartIndexState; break; case IndexBufferElementType.UShort: if (this.ushortRestartIndexState == null) { this.ushortRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.ushortRestartIndexState; break; case IndexBufferElementType.UInt: if (this.uintRestartIndexState == null) { this.uintRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.uintRestartIndexState; break; default: throw new NotDealWithNewEnumItemException(typeof(IndexBufferElementType)); } return(result); }
/// <summary> /// 遍历以<paramref name="lastVertexId"/>为最后一个顶点的图元, /// 瞄准每个图元的索引(例如1个三角形有3个索引)中的最后一个索引, /// 将此索引在<see cref="IndexBuffer"/>中的索引(位置)收集起来。 /// </summary> /// <param name="arg"></param> /// <param name="lastVertexId"></param> /// <returns></returns> private List <RecognizedPrimitiveInfo> GetLastIndexIdList(PickingEventArgs arg, uint lastVertexId) { var drawCmd = this.DrawCommand; DrawMode mode = drawCmd.Mode; PrimitiveRecognizer recognizer = PrimitiveRecognizerFactory.Create( (arg.GeometryType.Contains(GeometryType.Point) && mode.ToGeometryType() == GeometryType.Line) ? DrawMode.Points : mode); PrimitiveRestartState glState = GetPrimitiveRestartState(); List <RecognizedPrimitiveInfo> primitiveInfoList = null; if (glState == null) { primitiveInfoList = recognizer.Recognize(lastVertexId, drawCmd); } else { primitiveInfoList = recognizer.Recognize(lastVertexId, drawCmd, glState.RestartIndex); } return(primitiveInfoList); }
private PrimitiveRestartState GetPrimitiveRestartState(OneIndexBuffer indexBuffer) { PrimitiveRestartState result = null; switch (indexBuffer.ElementType) { case IndexBufferElementType.UByte: if (this.ubyteRestartIndexState == null) { this.ubyteRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.ubyteRestartIndexState; break; case IndexBufferElementType.UShort: if (this.ushortRestartIndexState == null) { this.ushortRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.ushortRestartIndexState; break; case IndexBufferElementType.UInt: if (this.uintRestartIndexState == null) { this.uintRestartIndexState = new PrimitiveRestartState(indexBuffer.ElementType); } result = this.uintRestartIndexState; break; default: throw new Exception("Unexpected IndexBufferElementType!"); } return(result); }
/// <summary> /// /// </summary> protected override void DoInitialize() { // init shader program. ShaderProgram program = this.renderProgramProvider.GetShaderProgram(); ShaderProgram pickProgram = this.pickProgramProvider.GetShaderProgram(); // init vertex attribute buffer objects. IBufferable model = this.DataSource; VertexBuffer positionBuffer = null; VertexShaderAttribute[] vertexAttributeBuffers; { var list = new List <VertexShaderAttribute>(); foreach (AttributeMap.NamePair item in this.attributeMap) { VertexBuffer buffer = model.GetVertexAttributeBuffer( item.NameInIBufferable, item.VarNameInShader); if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } list.Add(new VertexShaderAttribute(buffer, item.VarNameInShader)); if (item.VarNameInShader == this.PositionNameInVertexShader) { positionBuffer = buffer; } } vertexAttributeBuffers = list.ToArray(); } // 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (positionBuffer == null || positionBuffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); this.stateList.Add(glState); this.picker = new OneIndexPicker(this); } else { this.picker = new ZeroIndexPicker(this); } // init VAO. var vertexArrayObject = new VertexArrayObject(indexBuffer, vertexAttributeBuffers); vertexArrayObject.Initialize(program); var pickingVAO = new VertexArrayObject(indexBuffer, new VertexShaderAttribute(positionBuffer, "in_Position")); pickingVAO.Initialize(pickProgram); // sets fields. this.RenderProgram = program; this.PickProgram = pickProgram; this.vertexShaderAttributes = vertexAttributeBuffers; this.positionBuffer = positionBuffer; this.indexBuffer = indexBuffer; this.vertexArrayObject = vertexArrayObject; this.pickVertexArrayObject = pickingVAO; }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public IPickableRenderMethod ToRenderMethod(IBufferSource model) { // init shader program. ShaderProgram pickProgram = this.programProvider.GetShaderProgram(); // init vertex attribute buffer objects. var positionBuffers = new List <VertexBuffer>(); // position attribute is divided into blocks. // we only care about the position attribute. foreach (var buffer in model.GetVertexAttributeBuffer(this.positionNameInIBufferSource)) { if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } positionBuffers.Add(buffer); } int blockCount = positionBuffers.Count; // RULE: 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 foreach (var buffer in positionBuffers) { if (buffer == null || buffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } } // init draw command. var allDrawCommands = (from item in model.GetDrawCommand() where (item != null) select item).ToArray(); int cmdCount = allDrawCommands.Length; if (cmdCount != blockCount) { throw new Exception("Draw Commands count != vertex buffer block count."); } // init VAO. var pickingVAOs = new VertexArrayObject[cmdCount]; for (int b = 0; b < cmdCount; b++) { var vertexAttributeBuffers = new VertexShaderAttribute(positionBuffers[b], PickingShaderHelper.in_Position); pickingVAOs[b] = new VertexArrayObject(allDrawCommands[b], pickProgram, vertexAttributeBuffers); } var renderUnit = new IPickableRenderMethod(pickProgram, pickingVAOs, positionBuffers.ToArray(), this.states); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. foreach (var cmd in allDrawCommands) { var ptr = cmd as IHasIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.IndexBufferObject.ElementType); renderUnit.StateList.Add(glState); break; } } return(renderUnit); }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public RenderMethod ToRenderMethod(IBufferSource model) { // init shader program. ShaderProgram program = this.programProvider.GetShaderProgram(); // init vertex attribute buffer objects. var attrCount = this.map.Count(); // how many kinds of vertex attributes? var allBlocks = new List <VertexBuffer> [attrCount]; var allNames = new string[attrCount]; int blockCount = 0; // how many blocks an attribute is divided into? int index = 0; foreach (AttributeMap.NamePair item in this.map) { blockCount = 0; allBlocks[index] = new List <VertexBuffer>(); foreach (var buffer in model.GetVertexAttributeBuffer(item.NameInIBufferSource)) { if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } allBlocks[index].Add(buffer); allNames[index] = item.VarNameInShader; blockCount++; } if (blockCount != allBlocks[0].Count) { throw new Exception("Not all vertex attribute buffers' block count are the same!"); } index++; } // init draw commands. var drawCmds = (from item in model.GetDrawCommand() where (item != null) select item).ToArray(); int cmdCount = drawCmds.Length; if (attrCount > 0 && cmdCount != blockCount) { throw new Exception("Draw Commands count != vertex buffer block count."); } // init VAOs. var vaos = new VertexArrayObject[cmdCount]; for (int c = 0; c < cmdCount; c++) { var vertexShaderAttributes = new VertexShaderAttribute[attrCount]; for (int a = 0; a < attrCount; a++) { List <VertexBuffer> vertexAttribute = allBlocks[a]; string varNameInShader = allNames[a]; vertexShaderAttributes[a] = new VertexShaderAttribute(vertexAttribute[c], varNameInShader); } vaos[c] = new VertexArrayObject(drawCmds[c], program, vertexShaderAttributes); } var renderUnit = new RenderMethod(program, vaos, this.states); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care of this rule when designing a model's index buffer. foreach (var cmd in drawCmds) { var ptr = cmd as IHasIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.IndexBufferObject.ElementType); renderUnit.StateList.Add(glState); break; } } return(renderUnit); }