VBO中的自定义三角形,如何渲染
Posted
技术标签:
【中文标题】VBO中的自定义三角形,如何渲染【英文标题】:Custom Triangles in VBO, how to render 【发布时间】:2014-04-01 20:42:42 【问题描述】:一般来说,我想要的是以自定义方式读取特定的 vbo 缓冲区: 我有一个缓冲区-> 3 个三角形类的数组
class Triangle
public:
CD_FLOAT3 a;
CD_FLOAT3 b;
CD_FLOAT3 c;
CD_FLOAT3 direction;
CD_FLOAT velocity;
CD_FLOAT3 color;
这就是我生成 vbo 的方式:
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
我想要从我的渲染函数中渲染三角形的 3 个顶点,而不是跳过作为 sizeof(Triangle) (下一个元素)的步幅。所以我相应地将 glVertexPointer 定位到点 A、B、C 的 3 位置。我也只想要三角形上的一种颜色,所以我使用了一个 glColorPointer
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glVertexPointer( 3, GL_FLOAT, sizeof(Triangle), 0);
glVertexPointer(3, GL_FLOAT, sizeof(Triangle), (void*)12);
glVertexPointer(3, GL_FLOAT, sizeof(Triangle), (void*)24);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, sizeof(Triangle), (void*)(sizeof(CD_FLOAT)*13));
glDrawArrays(GL_TRIANGLES, 0, numTriangles);
glDisableClientState(GL_COLOR_ARRAY);
这个函数的结果只绘制一个三角形,每步一个点,我认为“glVertexPointer”只重新定位指针,所以只绘制第三个三角形。
我真正想知道的是如何读取缓冲区以绘制 3 个三角形:
-
三角形1:一个;乙; C;颜色;步幅:
三角形2:一个;乙; C;颜色;跨步
三角形3:一个;乙; C;颜色;
【问题讨论】:
为什么将其他数据与提供给着色器的数据结合在一起?上传GPU不需要的数据然后让它跳过,我可以让我工作,但真的不推荐;只需上传您绝对需要的内容。如果我理解正确,您会为每个渲染的三角形上传整个Triangle
吗?
你为什么要打三遍glVertexPointer()
?只有glDrawArrays()
之前的最后一次调用才会生效。
@legends2k 我知道将数据发送到着色器没有用,但我现在不关心。我如何指定一个接一个地调用 3 次,还有另一个 gl 调用吗?
@genpfault 如何指定调用 3 次后,是否还有另一个 gl 调用?
【参考方案1】:
你不能用固定功能的 OpenGL 做你想做的事。
你能做的最好的就是复制你的颜色属性信息并分离你的运动学状态:
class Vertex
public:
CD_FLOAT3 pos;
CD_FLOAT3 color;
;
class State
public:
CD_FLOAT3 direction;
CD_FLOAT velocity;
;
const unsigned int NumTris = ...;
std::vector< State > states( NumTris );
std::vector< Vertex > verts( NumTris * 3 );
PopulateAndBindVBO();
glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), 0 );
glColorPointer( 3, GL_FLOAT, sizeof(Vertex), sizeof(CD_FLOAT3) );
glDrawArrays(GL_TRIANGLES, 0, NumTris );
您可以使用几何着色器将Triangle
结构的数组拆分为三角形:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <vector>
#include <cstddef>
using namespace std;
#include <glm/glm.hpp>
using namespace glm;
struct Program
static GLuint Load( const char* vert, const char* geom, const char* frag )
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
private:
static void CheckStatus( GLuint obj )
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = 0 ;
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( -1 );
static void AttachShader( GLuint program, GLenum type, const char* src )
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
;
#define GLSL(version, shader) "#version " #version "\n" #shader
struct Triangle
glm::vec3 a;
glm::vec3 b;
glm::vec3 c;
glm::vec3 color;
glm::vec3 direction;
GLfloat velocity;
;
const char* vert = GLSL
(
330 core,
layout ( location = 0 ) in vec3 A;
layout ( location = 1 ) in vec3 B;
layout ( location = 2 ) in vec3 C;
layout ( location = 3 ) in vec3 Color;
out VertToGeom
vec3 A;
vec3 B;
vec3 C;
vec3 Color;
outData;
void main()
outData.A = A;
outData.B = B;
outData.C = C;
outData.Color = Color;
);
const char* geom = GLSL
(
330 core,
in VertToGeom
vec3 A;
vec3 B;
vec3 C;
vec3 Color;
inData[];
out GeomToFrag
vec3 Color;
outData;
layout ( points ) in;
layout ( triangle_strip, max_vertices = 3 ) out;
void main()
gl_Position.xyz = inData[ 0 ].A;
outData.Color = inData[ 0 ].Color;
EmitVertex();
gl_Position.xyz = inData[ 0 ].B;
outData.Color = inData[ 0 ].Color;
EmitVertex();
gl_Position.xyz = inData[ 0 ].C;
outData.Color = inData[ 0 ].Color;
EmitVertex();
EndPrimitive();
);
const char* frag = GLSL
(
330 core,
in GeomToFrag
vec3 Color;
inData;
void main()
gl_FragColor = vec4( inData.Color, 1.0 );
);
GLuint vbo = 0;
void display()
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
static GLuint prog = Program::Load( vert, geom, frag );
glUseProgram( prog );
vector< Triangle > tris( 2 );
tris[0].a = glm::vec3( 0, 0, 0 );
tris[0].b = glm::vec3( 1, 0, 0 );
tris[0].c = glm::vec3( 1, 1, 0 );
tris[0].color = glm::vec3( 1, 0, 0 );
tris[1].a = glm::vec3( 0, 0, 0 );
tris[1].b = glm::vec3( -1, 0, 0 );
tris[1].c = glm::vec3( -1, -1, 0 );
tris[1].color = glm::vec3( 0, 1, 0 );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( Triangle ) * tris.size(), &tris[0], GL_STREAM_DRAW );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 0 ) );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 1 ) );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 2 ) );
glEnableVertexAttribArray( 2 );
glVertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, sizeof( Triangle ), (void*)( sizeof( glm::vec3 ) * 3 ) );
glEnableVertexAttribArray( 3 );
glDrawArrays( GL_POINTS, 0, tris.size() );
glutSwapBuffers();
int main(int argc, char **argv)
glutInit( &argc, argv );
glutSetOption( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS );
glutInitContextVersion( 3, 3 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glewExperimental = GL_TRUE;
glewInit();
GLuint vao = 0;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glGenBuffers( 1, &vbo );
glutDisplayFunc( display );
glutMainLoop();
return 0;
【讨论】:
我正在使用相同的数组来调用三角形数组(vbo)上的 cuda 内核。所以你说我真的需要物理剥离所需的渲染数据,甚至添加更多的颜色变量,而不是实际使用相同的数组。好的,所以我的解决方案应该将顶点拆分为一个数组,还有颜色,并将运动状态作为一个单独的数组传递,而不是在 vbo 中使用它?该死的:/ 我觉得很奇怪opengl没有在缓冲区中跳过数据的功能:/ 没有比这更好的方法了,我可以使用 index_array 和所有 float3 作为索引参数,但这意味着我必须将浮点数从三角形中取出。谢谢你的帮助 【参考方案2】:你可以试试“glVertexAttribPointer” https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml
我认为您可以像这样存储数据:
struct vertex
//posision
float x;
float y;
float z;
//color
float r;
float g;
float b;
GLuint buffer;
static const vertex vertices[]=....;
glGenBuffers(1,&buffer);
glBindBuffer(GL_ARRAY_BUFFER,buffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//set up two vertex attributes---first positions
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(vertex),(void*)offsetof(vertex,x));
glEnableVertexAttribArray(0);
//now colors
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(vertex),(void*)offsetof(vertex,r));
glEnableVertexAttribArray(1);
【讨论】:
以上是关于VBO中的自定义三角形,如何渲染的主要内容,如果未能解决你的问题,请参考以下文章