//private readonly IBufferSource model; /// <summary> /// Scene node that supports 'Color-Coded-Picking'. /// </summary> ///<param name="model">Only <see cref="DrawArraysCmd"/> and <see cref="DrawElementsCmd"/> are supported as <see cref="IDrawCommand"/>.</param> /// <param name="positionNameInIBufferSource">The 'in' variable name which represents position buffer vertex shader.</param> ///<param name="builders"></param> public PickableNode(IBufferSource model, string positionNameInIBufferSource, params RenderMethodBuilder[] builders) : base(model, builders) { var pickProgramProvider = PickingShaderHelper.GetPickingShaderProgramProvider(); this.pickingRenderUnitBuilder = new IPickableRenderMethodBuilder(pickProgramProvider, positionNameInIBufferSource); }
/// <summary> /// 根据<see cref="IndexBufferPtr"/>的具体类型获取一个<see cref="PickableRenderer"/> /// </summary> /// <param name="bufferable"></param> /// <param name="propertyNameMap"></param> /// <param name="positionNameInIBufferable"></param> /// <param name="switches"></param> /// <returns></returns> public static InnerPickableRenderer GetRenderer( this IBufferable bufferable, PropertyNameMap propertyNameMap, string positionNameInIBufferable, params GLSwitch[] switches) { if (bufferable == null || propertyNameMap == null || string.IsNullOrEmpty(positionNameInIBufferable)) { throw new ArgumentNullException(); } IndexBufferPtr indexBufferPtr = bufferable.GetIndex(); if (indexBufferPtr is ZeroIndexBufferPtr) { return(new ZeroIndexRenderer(bufferable, PickingShaderHelper.GetShaderCodes(), propertyNameMap, positionNameInIBufferable, switches)); } else if (indexBufferPtr is OneIndexBufferPtr) { return(new OneIndexRenderer(bufferable, PickingShaderHelper.GetShaderCodes(), propertyNameMap, positionNameInIBufferable, switches)); } else { throw new NotImplementedException(); } }
protected override void DoInitialize() { // init shader program this.Program = PickingShaderHelper.GetPickingShaderProgram(); // init property buffer objects var propertyBufferPtrs = new PropertyBufferPtr[propertyNameMap.Count()]; int index = 0; foreach (var item in propertyNameMap) { PropertyBufferPtr bufferPtr = this.bufferable.GetProperty( item.NameInIBufferable, item.VarNameInShader); if (bufferPtr == null) { throw new Exception(); } propertyBufferPtrs[index++] = bufferPtr; } this.propertyBufferPtrs = propertyBufferPtrs; this.indexBufferPtr = this.bufferable.GetIndex(); foreach (var item in propertyNameMap) { PropertyBufferPtr bufferPtr = this.bufferable.GetProperty( item.NameInIBufferable, item.VarNameInShader); if (bufferPtr == null) { throw new Exception(); } if (item.NameInIBufferable == positionNameInIBufferable) { this.positionBufferPtr = new PropertyBufferPtr( "in_Position",// in_Postion same with in the PickingShader.vert shader bufferPtr.BufferId, bufferPtr.DataSize, bufferPtr.DataType, bufferPtr.Length, bufferPtr.ByteLength); break; } } // 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 = this.indexBufferPtr as OneIndexBufferPtr; if (ptr != null) { GLSwitch glSwitch = new PrimitiveRestartSwitch(ptr); this.switchList.Add(glSwitch); } // 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (this.positionBufferPtr.DataSize != 3 || this.positionBufferPtr.DataType != OpenGL.GL_FLOAT) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } }
/// <summary> /// 支持"拾取"的渲染器 /// </summary> /// <param name="model">一种渲染方式</param> /// <param name="renderProgramProvider">各种类型的shader代码</param> /// <param name="attributeMap">关联<paramref name="model"/>和<paramref name="shaderProgramProvider"/>中的属性</param> /// <param name="positionNameInVertexShader">vertex shader种描述顶点位置信息的in变量的名字</param> ///<param name="switches"></param> public PickableRenderer(IBufferable model, IShaderProgramProvider renderProgramProvider, AttributeMap attributeMap, string positionNameInVertexShader, params GLState[] switches) { this.PositionNameInVertexShader = positionNameInVertexShader; this.pickProgramProvider = PickingShaderHelper.GetPickingShaderProgramProvider(); this.DataSource = model; this.renderProgramProvider = renderProgramProvider; this.attributeMap = attributeMap; this.stateList.AddRange(switches); }
protected override void DoInitialize() { // init shader program this.shaderProgram = PickingShaderHelper.GetPickingShaderProgram(); // init property buffer objects var propertyBufferPtrs = new PropertyBufferPtr[propertyNameMap.Count()]; int index = 0; foreach (var item in propertyNameMap) { PropertyBufferPtr bufferPtr = this.bufferable.GetProperty( item.nameInIBufferable, item.VarNameInShader); if (bufferPtr == null) { throw new Exception(); } propertyBufferPtrs[index++] = bufferPtr; } this.propertyBufferPtrs = propertyBufferPtrs; this.indexBufferPtr = this.bufferable.GetIndex(); foreach (var item in propertyNameMap) { PropertyBufferPtr bufferPtr = this.bufferable.GetProperty( item.nameInIBufferable, item.VarNameInShader); if (bufferPtr == null) { throw new Exception(); } if (item.nameInIBufferable == positionNameInIBufferable) { this.positionBufferPtr = new PropertyBufferPtr( "in_Position",// in_Postion same with in the PickingShader.vert shader bufferPtr.BufferId, bufferPtr.DataSize, bufferPtr.DataType, bufferPtr.Length, bufferPtr.ByteLength); break; } } // 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (this.positionBufferPtr.DataSize != 3 || this.positionBufferPtr.DataType != OpenGL.GL_FLOAT) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } }
protected override void DoInitialize() { // init shader program ShaderProgram program = PickingShaderHelper.GetPickingShaderProgram(); var shaders = (from item in shaderCodes select item.CreateShader()).ToArray(); program.Create(shaders); this.shaderProgram = program; foreach (var item in shaders) { item.Delete(); } // init property buffer objects var propertyBufferPtrs = new PropertyBufferPtr[propertyNameMap.Count()]; int index = 0; foreach (var item in propertyNameMap) { if (index <= 0) { if (item.nameInIBufferable == this.positionNameInIBufferable) { PropertyBufferPtr bufferPtr = this.bufferable.GetProperty( item.nameInIBufferable, item.VarNameInShader); if (bufferPtr == null) { throw new Exception(); } propertyBufferPtrs[index++] = bufferPtr; this.positionBufferPtr = bufferPtr; } } else { if (item.nameInIBufferable == this.positionNameInIBufferable) { throw new Exception("More than 1 property named as position buffer~"); } } } this.propertyBufferPtrs = propertyBufferPtrs; this.indexBufferPtr = this.bufferable.GetIndex(); }
private void ColorCodedPickingRender(RenderEventArgs e) { if (this.pickingShaderProgram == null) { this.pickingShaderProgram = PickingShaderHelper.GetPickingShaderProgram(); } ShaderProgram program = this.pickingShaderProgram; // 绑定shader program.Bind(); var picking = this as IColorCodedPicking; // TODO: use uint/int/float or ? use UniformUInt instead program.SetUniform("pickingBaseID", picking.PickingBaseID); pickingMVP.SetUniform(program); foreach (var item in switchList) { item.On(); } if (this.vertexArrayObject4Picking == null) { var vertexArrayObject4Picking = new VertexArrayObject( this.indexBufferPtr, this.positionBufferPtr); vertexArrayObject4Picking.Create(e, program); this.vertexArrayObject4Picking = vertexArrayObject4Picking; } //else { this.vertexArrayObject4Picking.Render(e, program); } foreach (var item in switchList) { item.Off(); } pickingMVP.ResetUniform(program); // 解绑shader program.Unbind(); }
/// <summary> /// 根据<see cref="IndexBuffer"/>的具体类型获取一个<see cref="PickableRenderer"/> /// </summary> /// <param name="model"></param> /// <param name="attributeMap"></param> /// <param name="positionNameInIBufferable"></param> /// <param name="switches"></param> /// <returns></returns> public static InnerPickableRenderer GetRenderer( this IBufferable model, AttributeMap attributeMap, string positionNameInIBufferable, params GLState[] switches) { if (model == null || attributeMap == null || string.IsNullOrEmpty(positionNameInIBufferable)) { throw new ArgumentNullException(); } AttributeMap map = null; foreach (AttributeMap.NamePair item in attributeMap) { if (item.NameInIBufferable == positionNameInIBufferable) { map = new AttributeMap(); map.Add(item.VarNameInShader, item.NameInIBufferable); break; } } if (map == null) { throw new Exception(string.Format("No matching variable name in shader for [{0}]", positionNameInIBufferable)); } if (model.UsesZeroIndexBuffer()) { return(new ZeroIndexRenderer(model, PickingShaderHelper.GetShaderCodes(), map, positionNameInIBufferable, switches)); } else { return(new OneIndexRenderer(model, PickingShaderHelper.GetShaderCodes(), map, positionNameInIBufferable, switches)); } }