Last active
April 24, 2024 05:10
-
-
Save realark/d88866fa2fe2459f59e53620931ad155 to your computer and use it in GitHub Desktop.
opengl hello triangle on c++ and common lisp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <GL/glew.h> | |
#include <GL/glu.h> | |
#include <SDL2/SDL.h> | |
// compile and run: | |
// rm csdlopengl ; gcc -o csdlopengl ctraingle.cpp -lSDL2 -lGLEW -lstdc++ -lGL && ./csdlopengl | |
//*************************************************************************** | |
// The Width of the screen | |
//*************************************************************************** | |
const GLuint SCREEN_WIDTH = 800; | |
//*************************************************************************** | |
// The height of the screen | |
//*************************************************************************** | |
const GLuint SCREEN_HEIGHT = 600; | |
bool success = GL_TRUE; | |
const GLchar* vertexShaderSource = "#version 330 core\n" | |
"layout (location = 0) in vec3 position;\n" | |
"void main()\n" | |
"{\n" | |
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n" | |
"}\0"; | |
const GLchar* fragmentShaderSource = "#version 330 core\n" | |
"out vec4 color;\n" | |
"void main()\n" | |
"{\n" | |
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" | |
"}\n\0"; | |
int main(int argc, char *argv[]) | |
{ | |
//*********************************************************************** | |
// Initialize SDL | |
//*********************************************************************** | |
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) | |
{ | |
std::cout << "SDL could not initialize!SDL Error :" << | |
std::string(SDL_GetError()); | |
return EXIT_FAILURE; | |
} | |
else | |
{ | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, | |
SDL_GL_CONTEXT_PROFILE_CORE); | |
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); | |
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
//******************************************************************* | |
//The window we'll be rendering to | |
//******************************************************************* | |
SDL_Window *window = SDL_CreateWindow("Breakout", | |
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, | |
SCREEN_HEIGHT, SDL_WINDOW_SHOWN | | |
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); | |
if (window == NULL) | |
{ | |
std::cout << "Window could not be created!SDL_Error: " << | |
std::string(SDL_GetError()) << std::endl; | |
return EXIT_FAILURE; | |
} | |
//******************************************************************* | |
//OpenGL context | |
//******************************************************************* | |
SDL_GLContext context = SDL_GL_CreateContext(window); | |
//******************************************************************* | |
// Set the required callback functions | |
//******************************************************************* | |
SDL_Event windowEvent; | |
//******************************************************************* | |
//Use OpenGL 3.3 | |
//******************************************************************* | |
//******************************************************************* | |
// Set this to true so GLEW knows to use a modern approach to | |
// retrieving function pointers and extensions | |
//******************************************************************* | |
glewExperimental = GL_TRUE; | |
//******************************************************************* | |
// Initialize GLEW to setup the OpenGL Function pointers | |
//******************************************************************* | |
GLenum glewError = glewInit(); | |
if (GLEW_OK != glewError) | |
{ | |
std::cout << "Failed to initialize GLEW: " << | |
glewGetErrorString(glewError) << std::endl; | |
return EXIT_FAILURE; | |
} | |
glEnable(GL_CULL_FACE); | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
//******************************************************************* | |
// Define the viewport dimensions | |
//******************************************************************* | |
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | |
//******************************************************************* | |
// Build and compile our shader program | |
// Vertex shader | |
//******************************************************************* | |
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); | |
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); | |
glCompileShader(vertexShader); | |
//******************************************************************* | |
// Check for compile time errors | |
//******************************************************************* | |
GLint success; | |
GLchar infoLog[512]; | |
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); | |
if (!success) | |
{ | |
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); | |
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED: " << | |
infoLog << std::endl; | |
} | |
//******************************************************************* | |
// Fragment shader | |
//******************************************************************* | |
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); | |
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); | |
glCompileShader(fragmentShader); | |
//******************************************************************* | |
// Check for compile time errors | |
//******************************************************************* | |
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); | |
if (!success) | |
{ | |
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); | |
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: " << | |
infoLog << std::endl; | |
} | |
//******************************************************************* | |
// Link shaders | |
//******************************************************************* | |
GLuint shaderProgram = glCreateProgram(); | |
glAttachShader(shaderProgram, vertexShader); | |
glAttachShader(shaderProgram, fragmentShader); | |
glLinkProgram(shaderProgram); | |
//******************************************************************* | |
// Check for linking errors | |
//******************************************************************* | |
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); | |
if (!success) { | |
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); | |
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED: " << infoLog << std::endl; | |
} | |
glDeleteShader(vertexShader); | |
glDeleteShader(fragmentShader); | |
//******************************************************************* | |
// Set up vertex data (and buffer(s)) and attribute pointers | |
//******************************************************************* | |
GLfloat vertices[] = { | |
-0.5f, -0.5f, 0.0f, // Left | |
0.5f, -0.5f, 0.0f, // Right | |
0.0f, 0.5f, 0.0f // Top | |
}; | |
GLuint VBO, VAO; | |
glGenVertexArrays(1, &VAO); | |
glGenBuffers(1, &VBO); | |
//******************************************************************* | |
// Bind the Vertex Array Object first, then bind and set vertex | |
// buffer(s) and attribute pointer(s). | |
//******************************************************************* | |
glBindVertexArray(VAO); | |
glBindBuffer(GL_ARRAY_BUFFER, VBO); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, | |
GL_STATIC_DRAW); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), | |
(GLvoid*)0); | |
glEnableVertexAttribArray(0); | |
//******************************************************************* | |
// Note that this is allowed, the call to glVertexAttribPointer | |
// registered VBO as the currently bound vertex buffer object so | |
// afterwards we can safely unbind | |
//******************************************************************* | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
//******************************************************************* | |
// Unbind VAO (it's always a good thing to unbind any buffer/array to | |
// prevent strange bugs) | |
//******************************************************************* | |
glBindVertexArray(0); | |
//******************************************************************* | |
// DeltaTime variables | |
//******************************************************************* | |
GLdouble deltaTime = 0.0f; | |
Uint64 lastFrame = 0L; | |
Uint64 currentFrame = SDL_GetPerformanceCounter(); | |
while (true) | |
{ | |
//*************************************************************** | |
// Calculate delta time | |
//*************************************************************** | |
lastFrame = currentFrame; | |
currentFrame = SDL_GetPerformanceCounter(); | |
deltaTime = ((currentFrame - lastFrame) * 1000 / | |
(GLdouble)SDL_GetPerformanceFrequency()); | |
double tmpDeltaTime = deltaTime; | |
//std::cout << "Hello 1 - deltaTime: " << std::to_string(deltaTime) << | |
// std::endl; | |
if (SDL_PollEvent(&windowEvent)) | |
{ | |
if (windowEvent.type == SDL_QUIT) | |
{ | |
break; | |
} | |
} | |
//*************************************************************** | |
// Clear the colorbuffer and render | |
//*************************************************************** | |
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT); | |
//*************************************************************** | |
// Draw our first triangle | |
//*************************************************************** | |
glUseProgram(shaderProgram); | |
glBindVertexArray(VAO); | |
glDrawArrays(GL_TRIANGLES, 0, 3); | |
glBindVertexArray(0); | |
//*************************************************************** | |
// draw OpenGL: Swap the screen buffers | |
//*************************************************************** | |
SDL_GL_SwapWindow(window); | |
} | |
//*************************************************************** | |
// Properly de-allocate all resources once they've outlived their | |
// purpose | |
//*************************************************************** | |
glDeleteVertexArrays(1, &VAO); | |
glDeleteBuffers(1, &VBO); | |
SDL_GL_DeleteContext(context); | |
SDL_DestroyWindow(window); | |
SDL_Quit(); | |
} | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(in-package :cl-user) | |
(require :sdl2) | |
(require :cl-opengl) | |
(defvar *gl-triangle* nil) | |
(defvar *vao* nil) | |
(defvar *gl-buffer-address* nil) | |
(defvar *shader-program-id* nil) | |
(defparameter *vertex-shader-source* | |
"#version 330 core | |
layout (location = 0) in vec3 position; | |
void main() | |
{ | |
gl_Position = vec4(position.x, position.y, position.z, 1.0); | |
}") | |
(defparameter *fragment-shader-source* | |
"#version 330 core | |
out vec4 color; | |
void main() | |
{ | |
color = vec4(1.0f, 0.5f, 0.2f, 1.0f); | |
}") | |
(defun assert-no-shader-errors (shader-id) | |
(let ((success (cffi:foreign-alloc :int :initial-element 0))) | |
(unwind-protect | |
(progn | |
(%gl:get-shader-iv shader-id :compile-status success) | |
(when (/= 1 (cffi:mem-aref success :int)) | |
(error "OpenGl error:~%~A" (gl:get-shader-info-log shader-id)))) | |
(cffi:foreign-free success)))) | |
(defun assert-no-program-errors (program-id) | |
(let ((success (cffi:foreign-alloc :int :initial-element 0))) | |
(unwind-protect | |
(progn | |
(%gl:get-program-iv program-id :link-status success) | |
(when (/= 1 (cffi:mem-aref success :int)) | |
(error "OpenGl error:~%~A" (gl:get-program-info-log program-id)))) | |
(cffi:foreign-free success)))) | |
(defun basic-test () | |
"The kitchen sink." | |
(sdl2:with-init (:everything) | |
(format t "Using SDL Library Version: ~D.~D.~D~%" | |
sdl2-ffi:+sdl-major-version+ | |
sdl2-ffi:+sdl-minor-version+ | |
sdl2-ffi:+sdl-patchlevel+) | |
(progn | |
;; https://wiki.libsdl.org/SDL_GLattr | |
;; https://wiki.libsdl.org/SDL_GLprofile | |
(sdl2:gl-set-attr :context-major-version 3) | |
(sdl2:gl-set-attr :context-minor-version 3) | |
(sdl2:gl-set-attr :context-profile-mask | |
sdl2-ffi:+sdl-gl-context-profile-core+) | |
(sdl2:gl-set-attr :doublebuffer 1) | |
#+darwin | |
(sdl2:gl-set-attr :context-forward-compatible-flag | |
sdl2-ffi:+sdl-gl-context-forward-compatible-flag+)) | |
(sdl2:with-window (win :w 800 :h 600 | |
:flags '(:shown :opengl)) | |
(sdl2:with-gl-context (gl-context win) | |
(format t "Setting up window/gl.~%") | |
(progn | |
(sdl2:gl-make-current win gl-context) | |
;; https://wiki.libsdl.org/SDL_GL_SetSwapInterval#Remarks | |
;; first try for adaptive vsync | |
;; note: using the ffi directly to bypass the rc assertion in wrapper library | |
(gl:viewport 0 0 800 600) | |
;; shaders | |
(let ((vertex-shader (gl:create-shader :vertex-shader)) | |
(fragment-shader (gl:create-shader :fragment-shader))) | |
(gl:shader-source vertex-shader *vertex-shader-source*) | |
(gl:compile-shader vertex-shader) | |
(assert-no-shader-errors vertex-shader) | |
(gl:shader-source fragment-shader *fragment-shader-source*) | |
(gl:compile-shader fragment-shader) | |
(assert-no-shader-errors fragment-shader) | |
(setf *shader-program-id* (gl:create-program)) | |
(gl:attach-shader *shader-program-id* vertex-shader) | |
(gl:attach-shader *shader-program-id* fragment-shader) | |
(gl:link-program *shader-program-id*) | |
(assert-no-program-errors *shader-program-id*) | |
(gl:delete-shader vertex-shader) | |
(gl:delete-shader fragment-shader)) | |
(let ((vec #(-0.5 -0.5 0.0 | |
0.5 -0.5 0.0 | |
0.0 0.5 0.0))) | |
(setf *gl-triangle* | |
(loop :with gl-array = (gl:alloc-gl-array :float (length vec)) | |
:for i :from 0 :below (length vec) :do | |
(setf (gl:glaref gl-array i) | |
(elt vec i)) | |
:finally (return gl-array)))) | |
(setf *vao* (gl:gen-vertex-array)) | |
(setf *gl-buffer-address* (gl:gen-buffer)) | |
(gl:bind-vertex-array *vao*) | |
(gl:bind-buffer :array-buffer *gl-buffer-address*) | |
(gl:buffer-data :array-buffer | |
:static-draw | |
*gl-triangle*) | |
(gl:vertex-attrib-pointer 0 3 :float 0 (* 3 (cffi:foreign-type-size :float)) 0) | |
(gl:enable-vertex-attrib-array 0) | |
(gl:bind-buffer :array-buffer 0) | |
(gl:bind-vertex-array 0)) | |
(gl:clear-color 0.0 1.0 1.0 1.0) | |
;; main loop | |
(format t | |
"Beginning main loop.~% shader-program=~A~% vao=~A~% doublebuffers=~A~%" | |
*shader-program-id* | |
*vao* | |
(sdl2:gl-get-attr :doublebuffer)) | |
(sdl2:with-event-loop (:method :poll) | |
(:keydown (:keysym keysym) | |
(let ((scancode (sdl2:scancode-value keysym)) | |
(sym (sdl2:sym-value keysym)) | |
(mod-value (sdl2:mod-value keysym))) | |
(declare (ignore sym mod-value)) | |
(cond | |
((sdl2:scancode= scancode :scancode-q) (sdl2:push-event :quit))))) | |
(:idle () | |
(gl:clear :depth-buffer-bit :color-buffer-bit) | |
(gl:use-program *shader-program-id*) | |
(gl:bind-vertex-array *vao*) | |
(gl:draw-arrays :triangles 0 3) | |
(gl:bind-vertex-array 0) | |
(sdl2:gl-swap-window win) | |
(sleep 0.100)) | |
(:quit () t)) | |
(progn | |
(gl:use-program 0) | |
(gl:bind-vertex-array 0) | |
(gl:delete-vertex-arrays (list *vao*)) | |
(setf *vao* nil) | |
(gl:delete-buffers (list *gl-buffer-address*)) | |
(setf *gl-buffer-address* nil) | |
(gl:free-gl-array *gl-triangle*) | |
(setf *gl-triangle* nil) | |
(gl:delete-program *shader-program-id*) | |
(setf *shader-program-id* 0)) | |
(format t "Done!~%"))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment