我正在尝试使用Cuda 10.1和OpenGL 4.6互操作在屏幕上绘制一堆点。但是,现在我只是从CPU加载一个三角形进行测试。但是,我是OpenGL的新手,这是我第一次编写顶点数组对象。所以我想我要问的第一个问题是:我的VAO代码有什么问题?为什么我的三角形没有画?我试图尽我所能解决这个问题。 我的第二个问题: 如果我通过Cuda更改了与VAO关联的两个VBO内部的数据,VAO仍会更新并绘制更改吗?
这是我的代码(很抱歉,它没有被注释,我正处于时间紧迫状态):
GPUmain.h:
#include <cuda_runtime.h>
#include "device_launch_parameters.h"
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/remove.h>
#include <curand.h>
#include <GL/glew.h>
#include <SDL_opengl.h>
#include <cuda_gl_interop.h>
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
struct pos {
GLint x, y, z;
};
struct col {
GLubyte r, g, b, a;
};
struct phy {
GLdouble spd;
GLdouble dir;
};
struct ver {
pos p;
col c;
};
class GPU {
public:
static int nParticles;
static GLuint vboidP;
static GLuint vboidC;
static GLuint vaoid;
static GLuint vrshaderid;
static GLuint frshaderid;
static GLuint lkshaderid;
static cudaGraphicsResource *CGRp;
static cudaGraphicsResource *CGRc;
static const char* shaders[2];
static thrust::device_vector<ver> verts;
static void init(int w, int h);
static void compute();
static void render();
static void GPUmain();
static void free();
};
GPUmain.cu:
#include "GPUmain.cuh"
__global__ void uploadVerts(ver *ve, pos *po, col *co) {
int id = threadIdx.x + (blockDim.x * blockIdx.x);
po[id].x = ve[id].p.x;
po[id].y = ve[id].p.y;
po[id].z = ve[id].p.z;
co[id].r = ve[id].c.r;
co[id].g = ve[id].c.g;
co[id].b = ve[id].c.b;
co[id].a = ve[id].c.a;
}
__global__ void genGrid(ver *v) {
int i = threadIdx.x + (blockDim.x * blockIdx.x);
int x = i % 1920;
int y = i / 1920;
v[i].p.x = x;
v[i].p.y = y;
v[i].p.z = 0;
v[i].c.r = 127;
v[i].c.g = 255;
v[i].c.b = 0;
v[i].c.a = 255;
}
int GPU::nParticles;
GLuint GPU::vboidP;
GLuint GPU::vboidC;
GLuint GPU::vaoid;
GLuint GPU::vrshaderid;
GLuint GPU::frshaderid;
GLuint GPU::lkshaderid;
cudaGraphicsResource *GPU::CGRp;
cudaGraphicsResource *GPU::CGRc;
const char* GPU::shaders[2] = {
"#version 460\n"
"layout(location = 0) in vec3 vertex_position;"
"layout(location = 1) in vec4 vertex_colour;"
"out vec4 colour;"
"void main() {"
" colour = vertex_colour;"
" gl_Position = vec4(vertex_position, 1.0);"
"}"
,
"#version 460\n"
"in vec4 colour;"
"out vec4 frag_colour;"
"void main() {"
" frag_colour = colour;"
"}"
};
//collection of vertices to be simulated and rendered
thrust::device_vector<ver> GPU::verts;
void GPU::init(int w, int h)
{
/*nParticles = w * h;
verts.resize(nParticles, ver{ pos{0,0,0}, col{255,0,0,255} });
genGrid<<<nParticles/1024,1024>>>(thrust::raw_pointer_cast(&verts[0]));
cudaDeviceSynchronize();*/
pos vp[3] = {
pos{0,0,0},
pos{200,0,4},
pos{100,200,3}
};
col vc[3] = {
col{255,0,0,255},
col{0,255,0,255},
col{0,0,255,255}
};
vrshaderid = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vrshaderid, 1, &shaders[0], NULL);
glCompileShader(vrshaderid);
GLint success;
GLchar infoLog[512];
glGetShaderiv(vrshaderid, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vrshaderid, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
frshaderid = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frshaderid, 1, &shaders[1], NULL);
glCompileShader(frshaderid);
glGetShaderiv(frshaderid, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(frshaderid, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
lkshaderid = glCreateProgram();
glAttachShader(lkshaderid, vrshaderid);
glAttachShader(lkshaderid, frshaderid);
glLinkProgram(lkshaderid);
glGetProgramiv(lkshaderid, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(lkshaderid, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glGenVertexArrays(1, &vaoid);
glGenBuffers(1,&vboidP);
glGenBuffers(1, &vboidC);
glBindVertexArray(vaoid);
glBindBuffer(GL_ARRAY_BUFFER,vboidP);
glBufferData(GL_ARRAY_BUFFER,3*sizeof(pos),vp,GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_INT, GL_TRUE, 3 * sizeof(pos), NULL);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboidC);
glBufferData(GL_ARRAY_BUFFER,3*sizeof(col),vc, GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 3 * sizeof(col), NULL);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/*cudaGraphicsGLRegisterBuffer(&CGRp,vboidP,cudaGraphicsMapFlagsWriteDiscard);
cudaGraphicsGLRegisterBuffer(&CGRc,vboidC, cudaGraphicsMapFlagsWriteDiscard);*/
glBindVertexArray(0);
}
void GPU::compute()
{
}
void GPU::render()
{
/*pos *posi;
col *cols;
size_t sizep;
size_t sizec;
cudaGraphicsMapResources(1, &CGRp, 0);
cudaGraphicsMapResources(1, &CGRc, 0);
cudaGraphicsResourceGetMappedPointer((void**)&posi, &sizep, CGRp);
cudaGraphicsResourceGetMappedPointer((void**)&cols, &sizec, CGRc);
uploadVerts<<<nParticles/1024, 1024>>>(thrust::raw_pointer_cast(&verts[0]), posi, cols);
cudaDeviceSynchronize();
cudaGraphicsUnmapResources(1, &CGRp, 0);
cudaGraphicsUnmapResources(1, &CGRc, 0);*/
glClearColor(0, 0, 0, 0); // we clear the screen with black (else, frames would overlay...)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the buffer
glUseProgram(lkshaderid);
glBindVertexArray(vaoid);
glDrawArrays(GL_TRIANGLES,0,3);
glBindVertexArray(0);
}
void GPU::GPUmain()
{
compute();
render();
}
void GPU::free()
{
/*cudaGraphicsUnregisterResource(CGRp);
cudaGraphicsUnregisterResource(CGRc);*/
glDeleteVertexArrays(1,&vaoid);
glDeleteBuffers(1, &vboidP);
glDeleteBuffers(1, &vboidC);
verts.clear();
thrust::device_vector<ver>().swap(verts);
}
window.cpp:
bool Window::init()
{
//initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
log << "Failed to initialize SDL!\n";
return false;
}
//set window atributes
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//creat window
window = SDL_CreateWindow(
name.c_str(),
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
width,
height,
SDL_WINDOW_OPENGL
);
//create opengl context in the window
glcontext = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(1);
//check if the window was created
if (window == nullptr) {
log << "Failed to create window!\n";
return false;
}
//turn on experimental features
glewExperimental = GL_TRUE;
//initiallize glew
if (glewInit() != GLEW_OK) {
log << "Failed to Init GLEW";
return false;
}
//set drawing parameters
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -255, 0);
glPointSize(1);
glEnable(GL_BLEND); // Allow Transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // how transparency acts
std::cout << sizeof(ver);
GPU::init(width, height);
return true;
}
void Window::renderFrame()
{
GPU::render();
SDL_GL_SwapWindow(window); //swap buffers
}
答案 0 :(得分:3)
属性的类型是整数数据类型:
struct pos { GLint x, y, z; }; struct col { GLubyte r, g, b, a; };
因此,当您设置通用顶点属性数据的数组而不是I
时,必须使用glVertexAttribIPointer
(着重于 glVertexAttribPointer
)。
顶点着色器属性的数据类型也必须是整数数据类型:
layout(location = 0) in vec3 vertex_position
layout(location = 1) in vec4 vertex_colour;
layout(location = 0) in ivec3 vertex_position;
layout(location = 1) in ivec4 vertex_colour;
stride
/ glVertexAttribIPointer
的{{1}}参数在连续的通用顶点属性之间的字节偏移。因此它必须分别是glVertexAttribPointer
sizeof(pos)
,而不是sizeof(col)
和3*sizeof(pos)
。
如果将通用顶点属性紧密压缩,则可以将3*sizeof(col)
设置为0。这是一种特殊情况,其中,步幅由stride
和size
参数自动计算:>
type
核心配置文件上下文(glBindBuffer(GL_ARRAY_BUFFER,vboidP);
// [...]
glVertexAttribIPointer(0, 3, GL_INT, 0, NULL);
// [...]
glBindBuffer(GL_ARRAY_BUFFER, vboidC);
// [...]
glVertexAttribIPointer(1, 4, GL_UNSIGNED_BYTE, 0, NULL);
// [...]
)不支持固定功能矩阵堆栈。
SDL_GL_CONTEXT_PROFILE_CORE
请参见Fixed Function Pipeline和Legacy OpenGL。
OpenGL gluLookat not working with shaders on的答案也可能有帮助。
我建议使用OpenGL Mathematics之类的库通过ortho()
和一个uniform变量来计算视图矩阵:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -255, 0);
version 460
layout(location = 0) in ivec3 vertex_position;
layout(location = 7) uniform mat4 prj_matrix;
void main()
{
// [...]
gl_Position = prj_matrix * vec4(vertex_position, 1.0);"
}
统一位置由Layout qualifier(#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// [...]
void GPU::render()
{
// [...]
glUseProgram(lkshaderid);
glm::mat4 prj = glm::ortho(0.0f, (float)width, 0.0f, (float)height, -255.0f, 0.0f);
glUniformMatrix4fv(7, 1, GL_FALSE, glm::value_ptr(prj));
// [...]
}
)显式设置。
glUniformMatrix4fv
在默认的统一块中的指定位置设置统一的值。这必须在glUseProgram
安装了progroam之后完成。
使用Raw string literal的完整着色器代码:
location = 7
如果应用建议的更改,则会看到以下三角形: