如何用SDL2和OpenGL画三角形?

2024-04-16

我正在使用 C++ 中的 SDL2 和 OpenGL 开发一个简单的应用程序。

问题是我的程序没有绘制三角形。

Rect.hpp(绘制三角形的类):

#ifndef Rect_hpp
#define Rect_hpp

#include <stdio.h>
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include "Shaders.hpp"

using namespace std;

extern GLfloat vertices[];

class Rect
{

public:
 Rect();
 ~Rect();
 void init();
void draw();

private:
 void bind();

 GLuint VAO;
 GLuint VBO;
 GLuint vertexShader;
 GLuint fragmentShader;
 GLuint shaderProgram;
 Shaders shaders;

};

#endif /* Rect_hpp */

矩形.cpp:

#include "Rect.hpp"

GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
};

Rect::Rect()
{
VBO = NULL;
vertexShader = NULL;
fragmentShader = NULL;
shaderProgram = NULL;
}

Rect::~Rect()
{
glDeleteShader(vertexShader);
vertexShader = NULL;
glDeleteShader(fragmentShader);
fragmentShader = NULL;
}

void Rect::bind()
{
glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO); //VBO activation
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat (GLvoid*)0);
    glEnableVertexAttribArray(0);

glBindVertexArray(0);
}

void Rect::init()
{
//VAO
glGenVertexArrays(1, &VAO); //VAO creation

//VBO
glGenBuffers(1, &VBO); //VBO creation

//SHADER
vertexShader = glCreateShader(GL_VERTEX_SHADER); //vertex shader
glShaderSource(vertexShader, 1, &shaders.vertexSource, NULL);
glCompileShader(vertexShader);

fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //fragment shader
glShaderSource(fragmentShader, 1, &shaders.fragmentSource, NULL);
glCompileShader(fragmentShader);

shaderProgram = glCreateProgram(); //shader program
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

bind();
}

void Rect::draw()
{
 glUseProgram(shaderProgram);
 glBindVertexArray(VAO);
 glDrawArrays(GL_TRIANGLES, 0, 3);
 glBindVertexArray(0);
}

游戏.hpp:

#ifndef Game_hpp
#define Game_hpp

#include <stdio.h>
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <OpenGL/gl3.h>
#include "glm/glm.hpp"
#include "Rect.hpp"

  using namespace glm;
  using namespace std;

  class Game
{

public:
Game(int width, int height);
~Game();
void run();

private:
int _width, _height;

void init();
void loop();
void input();
void draw();

SDL_Window* window;
SDL_GLContext context;
bool isRunning;
SDL_Event e;
Rect* rect;

};

#endif /* Game_hpp */

游戏.cpp:

#include "Game.hpp"

Game::Game(int width, int height)
{
 _width = width;
 _height = height;

window = NULL;
context = NULL;

rect = new Rect();

 isRunning = true;
}

 Game::~Game()
 {
 SDL_GL_DeleteContext(context);
 context = NULL;
 SDL_DestroyWindow(window);
 window = NULL;
 SDL_Quit();
 }

void Game::run()
{
 init();
 loop();
}

void Game::init()
{
 //SDL INIT
 SDL_Init(SDL_INIT_EVERYTHING);

 //OPENGL ATTRIBUTES
 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,  SDL_GL_CONTEXT_PROFILE_CORE);
 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

  //WINDOW INIT
  window = SDL_CreateWindow("OpenGL_GAME_TEST",
                          SDL_WINDOWPOS_CENTERED,
                          SDL_WINDOWPOS_CENTERED,
                          _width,
                          _height,
                          SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
glViewport(0, 0, _width, _height);

//OPENGL CONTEXT INIT
context = SDL_GL_CreateContext(window);

//GLEW INIT
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
    cout << "ERROR: GLEW initialization failed!" << endl;

//CLASSES INIT
rect->init();

}

void Game::loop()
{
while(isRunning)
{
    input();
    draw();
}
}

void Game::input()
{
if(SDL_PollEvent(&e))
{

    if(e.type == SDL_QUIT) isRunning = false;
    if(e.type == SDL_KEYDOWN)
        if(e.key.keysym.sym == SDLK_ESCAPE) isRunning = false;

}
}

void Game::draw()
{
//DRAW...
glClearColor(0.2f, 0.4f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

rect->draw();

SDL_GL_SwapWindow(window);
}

着色器.hpp:

#ifndef Shaders_hpp
#define Shaders_hpp

#include <stdio.h>
#include <iostream>
#include <GL/glew.h>

  class Shaders
{

public:
Shaders();
~Shaders();
const GLchar* vertexSource;
const GLchar* fragmentSource;

};

#endif /* Shaders_hpp */

着色器.cpp:

#include "Shaders.hpp"

Shaders::Shaders()
{
vertexSource = "#version 330 core \n"
               "layout (location = 0) in vec3 position; \n"
               "void main() \n"
               "{ \n"
               "    gl_Position = vec4(position, 1.0); \n"
               "} \n \0";

fragmentSource = "#version 330 core \n"
                 "out vec4 color \n"
                 "void main() \n"
                 "{ \n"
                 "  color = vec4(1.0, 0.5, 0.1, 1.0); \n"
                 "}; \n \0";
 }

Shaders::~Shaders()
{ 

}

最小可运行示例

main.c

#include <stdio.h>

#include <SDL2/SDL.h>
#define GLEW_STATIC
#include <GL/glew.h>

static const GLuint WIDTH = 512;
static const GLuint HEIGHT = 512;
static const GLchar* vertex_shader_source =
    "#version 120\n"
    "attribute vec2 coord2d;\n"
    "void main() {\n"
    "    gl_Position = vec4(coord2d, 0.0, 1.0);\n"
    "}\n";
static const GLchar* fragment_shader_source =
    "#version 120\n"
    "void main() {\n"
    "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    "}\n";
static GLfloat vertices[] = {
     0.0,  0.8,
    -0.8, -0.8,
     0.8, -0.8,
};

GLuint common_get_shader_program(
    const char *vertex_shader_source,
    const char *fragment_shader_source
) {
    GLchar *log = NULL;
    GLint log_length, success;
    GLuint fragment_shader, program, vertex_shader;

    /* Vertex shader */
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &log_length);
    log = malloc(log_length);
    if (log_length > 0) {
        glGetShaderInfoLog(vertex_shader, log_length, NULL, log);
        printf("vertex shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("vertex shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Fragment shader */
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetShaderInfoLog(fragment_shader, log_length, NULL, log);
        printf("fragment shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("fragment shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Link shaders */
    program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetProgramInfoLog(program, log_length, NULL, log);
        printf("shader link log:\n\n%s\n", log);
    }
    if (!success) {
        printf("shader link error");
        exit(EXIT_FAILURE);
    }

    /* Cleanup. */
    free(log);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return program;
}

int main(void) {
    GLint attribute_coord2d;
    GLuint program, vbo;
    SDL_Event event;
    SDL_GLContext gl_context;
    SDL_Window *window;

    SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
    window = SDL_CreateWindow(__FILE__, 0, 0,
            WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
    gl_context = SDL_GL_CreateContext(window);
    glewInit();

    /* Shader setup. */
    program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
    attribute_coord2d = glGetAttribLocation(program, "coord2d");

    /* Buffer setup. */
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    /* Global draw state */
    glUseProgram(program);
    glViewport(0, 0, WIDTH, HEIGHT);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    /* Main loop. */
    while (1) {
        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(attribute_coord2d);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(attribute_coord2d);
        SDL_GL_SwapWindow(window);
        if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
            break;
    }

    /* Cleanup. */
    glDeleteBuffers(1, &vbo);
    glDeleteProgram(program);
    SDL_GL_DeleteContext(gl_context);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

GitHub 上游 https://github.com/cirosantilli/cpp-cheat/blob/7b5ee8a90dc0355e1a0908e9b89cc0f6b5e41e0e/sdl/opengl.c.

编译并运行:

sudo apt-get install libsdl2-dev
gcc -lSDL2 -lGL -lGLEW -o main.out main.c
./main.out

有关 OpenGL 特定部分的更多信息:OpenGL 中“立即模式”是什么意思? https://stackoverflow.com/questions/6733934/what-does-immediate-mode-mean-in-opengl/36166310#36166310

在 Ubuntu 16.04 上测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用SDL2和OpenGL画三角形? 的相关文章

  • 跳转到文件行c#

    我如何跳到文件中的某些行 例如 c text txt 中的第 300 行 using var reader new StreamReader c test txt for int i 0 i lt 300 i reader ReadLine
  • 为什么 strcat() 之后字符串会被改变?

    这是源代码 int main char str dance char str1 hello char str2 abcd strcat str1 str2 printf s str output bcd why str更改后strcat s
  • 解决方案将无法构建,因为它无法从服务生成的类型转换为我的类型

    我有一个 WCF 服务项目 它构建得很好 可以生成可访问的 WSDL 并且 svcutil exe 不会生成任何错误 我有一个访问该 Web 服务的 服务管理器 项目 并且我已成功向其中添加了服务引用 ABCService 第三个项目包含我
  • 有没有办法在 .Net 中创建“自托管”网站? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 类似于 WCF 自托管 有没有办法创建一个在控制台应用程序中 自托管 的网站或dll 提出这个问题的方
  • 提升解析器中的 Spirit 段错误

    我一直在尝试将我在本科编译器中编写的一些 lex 和 yacc 代码转换为精神代码以学习精神 我发现了一个我似乎无法弄清楚的段错误 我这样写了词法分析器 namespace lex boost spirit lex enum Tokens
  • 是否可以将向量的一部分作为向量发送给函数? [复制]

    这个问题在这里已经有答案了 我想看看是否可以将向量的一部分传递给函数 以便它显示为函数的法线向量 更重要的是 我希望这可以在 O 1 的常数时间内完成 我不想迭代向量来创建一个新向量 事实上 我还希望在下面的示例中将新向量的大小更改为 40
  • 公开 ASP.NET 用户控件中的复杂属性

    我想从自定义 ASP NET 用户控件公开一个复杂的属性 可以通过aspx页面中的控制标签来设置 像这样的事情 public class TestData public int X public int Y public partial c
  • 从 C 调用带有字符串参数的 Go 函数?

    我可以从 C 调用一个没有参数的 Go 函数 按照下面的 https github com joeprivacy crefgo hello world 这通过编译go build和打印 Hello from Golang main func
  • 使用 JsonWriter 时,WriteStartConstructor 的用途是什么?

    标题说明了一切 我看到它 及其相应的结尾 吐出以下内容 new Foo 但我不明白什么new实际上是在反序列化时执行的 文档只是说它编写了一个 Json 构造函数 但没有说 Json 构造函数是什么is 此方法是作为增强功能的一部分引入的
  • 测试 WebApi 控制器时如何生成 Asp.net 用户身份

    我正在使用 Web API 2 在 web api 控制器中我使用过GetUserId使用 Asp net Identity 生成用户 ID 的方法 我必须为该控制器编写 MS 单元测试 如何从测试项目访问用户 ID 我在下面附上了示例代码
  • MDI应用程序中父窗体的问题

    我使用按钮作为容器中的控件 父窗体 当子窗体出现时 父窗体中的控件 按钮 图片 标签 出现在子窗体上并将其覆盖 我看不到子窗体 有谁知道如何防止这种情况 我不想将这些控件设置为 Control Visible false 因为当我最小化子表
  • C++ 中“return *this”是什么意思?

    我正在将 C 程序转换为 C 但这部分让我感到困惑 return this 是什么意思 template lt EDemoCommands msgType typename PB OBJECT TYPE gt class CDemoMess
  • 为 C# 和 C++ 应用程序编写 DLL

    我需要编写几个 DLL 它们都可以从 C 应用程序和 C 应用程序访问 最初 我认为通过用 C 编写 DLL 并从 C 和 C 应用程序链接到它们可以节省时间 精力 这种方法明智吗 还是应该使用 C 编写 DLL 我的建议是在您最舒服的地方
  • 可变长度数组性能影响 (C/C++)

    我正在编写一个相当简单的函数 它将数组发送到文件描述符 但是 为了发送数据 我需要附加一个一字节标头 这是我正在做的事情的简化版本 它似乎有效 void SendData uint8 t buffer size t length uint8
  • 使用 ASP.NET Core Identity 将令牌保存在 Cookie 中

    我想在我的 身份 生成的 cookie 中保存一些内容 我目前正在使用文档中的默认身份设置 启动 cs services Configure
  • IBM Rhapsody 中状态图终止连接器的理解

    在IBM Rhapsody中 如果我使用new创建了一个类的实例 那么我们是否必须通过调用delete来处理内存的释放 或者Termination Connector将在其状态图中通过内存释放来处理其销毁 如果您使用 C 和 OXF 对象执
  • 三角形未在 OSX 上的 OpenGL 2.1 中绘制

    我正在学习有关使用 OpenGL 在 Java 中创建游戏引擎的教程 我正在尝试在屏幕上渲染一个三角形 一切运行良好 我可以更改背景颜色 但三角形不会显示 我还尝试运行作为教程系列的一部分提供的代码 但它仍然不起作用 教程链接 http b
  • 非数字输入导致死循环

    由于某种原因 如果用户输入了错误的数据类型 例如 j 或 循环将停止要求输入并继续显示 Enter an integer gt 一遍又一遍 如何让程序处理错误的输入 为什么输入非数字值会导致如此奇怪的行为 define SENTINEL 0
  • 生成唯一随机数的智能方法

    我想生成 00000001 到 99999999 范围内的唯一随机数序列 所以第一个可能是 00001010 第二个可能是 40002928 等等 最简单的方法是生成一个随机数并将其存储在数据库中 下次再执行一次并检查数据库中该数字是否已存
  • C++ 模板类问题中的类型条件

    使用海湾合作委员会4 2 我有这个条件类型的元模板 template

随机推荐