我正在研究一个简单的OpenGL ES 2.0程序(与SDL 2一起使事情变得更容易),并决定尝试点精灵。我能够让它们成功绘制,但我无法通过从顶点着色器输出gl_PointSize来改变它们的大小。从理论上讲,这应该是我必须做的一切。
以下代码片段是我的几乎没有C ++代码的简化版本(根本没有错误检查,但这是因为它没有任何问题)它演示了我如何尝试更改我的点精灵的大小。它已经在具有类似结果的两台相当不同的计算机上进行了测试(Linux,但是32位/软件渲染与64位/离散GPU),并且可以使用g ++与g++ main.cpp -lSDL2 -Wall -D_REENTRANT -lGLESv2
进行编译。
#include <GLES2/gl2.h>
#include <SDL2/SDL.h>
struct myData {
SDL_Window *window;
SDL_GLContext context;
};
const GLchar vertex[] =
"#version 100\n"
"precision mediump float;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
" gl_PointSize = 128.0;\n"
"}\0";
const GLchar fragment[] =
"#version 100\n"
"precision mediump float;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\0";
GLuint loadShader(GLuint program, GLenum type, const GLchar *shaderSrc) {
GLuint shader;
shader = glCreateShader(type);
glShaderSource(shader, 1, &shaderSrc, NULL);
glCompileShader(shader);
glAttachShader(program, shader);
return 0;
}
int sdlInit(myData *data) {
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
data->window = SDL_CreateWindow("Demo", 0, 0, 512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
data->context = SDL_GL_CreateContext(data->window);
return 0;
}
int glInit(myData *data) {
GLuint programObject;
programObject = glCreateProgram();
loadShader(programObject, GL_VERTEX_SHADER, vertex);
loadShader(programObject, GL_FRAGMENT_SHADER, fragment);
glLinkProgram(programObject);
glUseProgram(programObject);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glViewport(0, 0, 512, 512);
return 0;
}
int loopFunc(myData *data) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
return 1;
}
}
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 1);
SDL_GL_SwapWindow(data->window);
return 0;
}
void sdlQuit(myData *data) {
SDL_GL_DeleteContext(data->context);
SDL_DestroyWindow(data->window);
SDL_Quit();
return;
}
int main() {
myData data;
sdlInit(&data);
glInit(&data);
while (!loopFunc(&data));
sdlQuit(&data);
return 0;
}
运行时,程序应该按照我在顶点着色器中设置的值生成一个大小为128像素的点精灵。然而,当实际执行时,窗口中心的点精灵的大小恰好是一个像素。我究竟做错了什么?
我想你忘了初始化opengles2上下文。
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
几件事:
#version 100
GLSL代码的常规桌面OpenGL上下文;桌面OpenGL要求您通过gl_PointSize
打开glEnable(GL_PROGRAM_POINT_SIZE)
。gl_PointSize
,确保你的GL实现实际上支持128.0
的GL_ALIASED_POINT_SIZE_RANGE
;规范只要求实现支持1.0到1.0的范围,任何高于该范围的都是可选的。在这个Debian Buster盒子上工作得很好:
SDL / OpenGL ES信息:
SDL compiled version: 2.0.9
SDL linked version : 2.0.9
GL_VENDOR : X.Org
GL_RENDERER : AMD Radeon (TM) R9 Fury Series (FIJI, DRM 3.27.0, 4.19.0-2-amd64, LLVM 7.0.1)
GL_VERSION : OpenGL ES 3.2 Mesa 18.3.4
GLSL version: OpenGL ES GLSL ES 3.20
gl_PointSize min: 1
gl_PointSize max: 2048
码:
// g++ `pkg-config --cflags sdl2 glesv2` main.cpp `pkg-config --libs sdl2 glesv2`
#include <SDL.h>
#include <SDL_opengles2.h>
#include <iostream>
void CheckStatus( GLuint obj, bool isShader )
{
GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
std::cerr << (GLchar*)log << "\n";
std::exit( EXIT_FAILURE );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader, true );
glAttachShader( program, shader );
glDeleteShader( shader );
}
const char* const vert = 1 + R"GLSL(
#version 100
precision mediump float;
void main()
{
gl_Position = vec4( 0.0, 0.0, 0.0, 1.0 );
gl_PointSize = 128.0;
}
)GLSL";
const char* const frag = 1 + R"GLSL(
#version 100
precision mediump float;
void main()
{
gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}
)GLSL";
int main( int argc, char** argv )
{
SDL_Init( SDL_INIT_VIDEO );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
SDL_Window *window = SDL_CreateWindow( "SDL2", 0, 0, 640, 480, SDL_WINDOW_OPENGL );
SDL_GLContext context = SDL_GL_CreateContext( window );
// SDL info
SDL_version compiled;
SDL_version linked;
SDL_VERSION( &compiled );
SDL_GetVersion( &linked );
std::cout << "SDL compiled version: " << (int)compiled.major << "." << (int)compiled.minor << "." << (int)compiled.patch << "\n";
std::cout << "SDL linked version : " << (int)linked.major << "." << (int)linked.minor << "." << (int)linked.patch << "\n";
// GL info
std::cout << "GL_VENDOR : " << glGetString( GL_VENDOR ) << "\n";
std::cout << "GL_RENDERER : " << glGetString( GL_RENDERER ) << "\n";
std::cout << "GL_VERSION : " << glGetString( GL_VERSION ) << "\n";
std::cout << "GLSL version: " << glGetString( GL_SHADING_LANGUAGE_VERSION ) << "\n";
float pointSizeRange[2] = { -1.0, -1.0 };
glGetFloatv( GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange );
std::cout << "gl_PointSize min: " << pointSizeRange[0] << "\n";
std::cout << "gl_PointSize max: " << pointSizeRange[1] << "\n";
GLuint prog = glCreateProgram();
AttachShader( prog, GL_VERTEX_SHADER, vert );
AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog, false );
glUseProgram( prog );
bool running = true;
while( running )
{
SDL_Event ev;
while( SDL_PollEvent( &ev ) )
{
if( ev.type == SDL_QUIT )
{
running = false;
}
}
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT );
glDrawArrays( GL_POINTS, 0, 1 );
SDL_GL_SwapWindow( window );
}
SDL_GL_DeleteContext( context );
SDL_DestroyWindow( window );
SDL_Quit();
return EXIT_SUCCESS;
}