Почему эта простая программа OpenGL ES 2.0/SDL 2 не позволяет мне изменять размер точечного спрайта?
Я работал над простой программой 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 пикселей в соответствии со значением, которое я установил в вершинном шейдере. Однако при фактическом выполнении размер спрайта точек в центре окна составляет ровно один пиксель. Что я делаю неправильно?
1 ответ
Пара вещей:
- Как отметил jumapico, убедитесь, что вы действительно запрашиваете контекст ES 2.0 из SDL, в противном случае вы можете получить обычный контекст OpenGL для настольного компьютера, который поддерживает OpenGL ES.
#version 100
Код GLSL; OpenGL рабочего стола требует, чтобы вы включилиgl_PointSize
с помощьюglEnable(GL_PROGRAM_POINT_SIZE)
, - Убедитесь, что ваша реализация GL на самом деле поддерживает
gl_PointSize
из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;
}
Я думаю, что вы забыли инициализировать контекст 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);