struct SpriteAnimator { unsigned int currentFreme; unsigned int rows; unsigned int columns; };
SpriteAnimator initSpriteAnimation( int rows, int columns, float * texCoord) { SpriteAnimator animator; animator.currentFreme = 0; animator.rows = rows; animator.columns = columns; spriteAnimationUpdate(animator, texCoord); return animator; } void spriteAnimationNextFrame(SpriteAnimator & animator, float * texCoord) { const int maxFrame = animator.columns * animator.rows - 1; if (maxFrame == animator.currentFreme) { animator.currentFreme = 0; } else { animator.currentFreme++; } spriteAnimationUpdate(animator, texCoord); } void spriteAnimationUpdate(SpriteAnimator & animator, float * texCoord) { const int X = 0; const int Y = 1; const int V0 = 0; const int V1 = 2; const int V2 = 4; const int V3 = 6; const float frameWidth = 1.f / animator.columns; const float frameHeight = 1.f / animator.rows; const int row = animator.rows - animator.currentFreme / animator.columns; const int col = animator.currentFreme % animator.columns; texCoord[V0 + X] = frameWidth * col; texCoord[V0 + Y] = frameHeight * row; texCoord[V1 + X] = frameWidth * (col + 1); texCoord[V1 + Y] = frameHeight * row; texCoord[V2 + X] = frameWidth * (col + 1); texCoord[V2 + Y] = frameHeight * (row + 1); texCoord[V3 + X] = frameWidth * col; texCoord[V3 + Y] = frameHeight * (row + 1); }
while (!glfwWindowShouldClose(window)) { render(shader); Sleep(1000 / 25); spriteAnimationNextFrame(animator, texCoord); glfwSwapBuffers(window); glfwPollEvents(); }
#include <chrono> #include <thread> #include <GL\glew.h> #include <GLFW\glfw3.h> #include <FreeImage.h> #define Sleep(ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms)); float position[] = {-1.f, -1.f, 0, 1.f, -1.f, 0, 1.f, 1.f, 0, -1.f, 1.f, 0}; float texCoord[] = { 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 1.f }; GLuint indexes[] = { 0, 1,2, 2,3,0}; const char vertexShader[] = "attribute vec4 a_position;" "attribute vec2 a_texCoord;" "out vec2 v_texCoord;" "void main(void) {" " v_texCoord = a_texCoord;" " gl_Position = a_position;" "}"; const char fragmentShader[] = "uniform sampler2D text;" "in vec2 v_texCoord;" "void main (void) { " " gl_FragColor = texture(text, v_texCoord);" "}"; struct Shader { GLuint program; GLuint position; GLuint texCoord; GLuint tex; }; struct SpriteAnimator { unsigned int currentFreme; unsigned int rows; unsigned int columns; }; GLuint loadTexture(const char * path) { int w, h; GLuint tex; FIBITMAP *dib(0); FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(path, 0); if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(path); if (fif == FIF_UNKNOWN) return -1; if (FreeImage_FIFSupportsReading(fif)) { dib = FreeImage_Load(fif, path); if (!dib) return -1; } w = FreeImage_GetWidth(dib); h = FreeImage_GetHeight(dib); const char * data = (const char *)FreeImage_GetBits(dib); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); return tex; } Shader createShader() { Shader shader; GLint statusF, statusV; GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); char * srcPrt; srcPrt = (char *)vertexShader; glShaderSource(vertexShaderId, 1, (const GLchar **)&srcPrt, NULL); srcPrt = (char *)fragmentShader; glShaderSource(fragmentShaderId , 1, (const GLchar **)&srcPrt, NULL); glCompileShader(vertexShaderId); glCompileShader(fragmentShaderId); glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &statusV); glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &statusF); if (statusV == GL_FALSE){ /* */ } if (statusF == GL_FALSE) { /* */ } shader.program = glCreateProgram(); glAttachShader(shader.program, vertexShaderId); glAttachShader(shader.program, fragmentShaderId); glLinkProgram(shader.program); glUseProgram(shader.program); shader.position = glGetAttribLocation(shader.program, "a_position"); shader.texCoord = glGetAttribLocation(shader.program, "a_texCoord"); glEnableVertexAttribArray(shader.position); glEnableVertexAttribArray(shader.texCoord); shader.tex = loadTexture("FireSpriteSheet.jpg"); return shader; } void render(Shader & shader) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0., 0., 0., 1.); glUseProgram(shader.program); glBindTexture(GL_TEXTURE_2D, shader.tex); glVertexAttribPointer(shader.position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), position); glVertexAttribPointer(shader.texCoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), texCoord); glDrawElements(GL_TRIANGLES, sizeof(indexes) / sizeof(indexes[0]), GL_UNSIGNED_INT, indexes); glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(0); return; } void spriteAnimationUpdate(SpriteAnimator & animator, float * texCoord); SpriteAnimator initSpriteAnimation( int rows, int columns, float * texCoord) { SpriteAnimator animator; animator.currentFreme = 0; animator.rows = rows; animator.columns = columns; spriteAnimationUpdate(animator, texCoord); return animator; } void spriteAnimationNextFrame(SpriteAnimator & animator, float * texCoord) { const int maxFrame = animator.columns * animator.rows - 1; if (maxFrame == animator.currentFreme) { animator.currentFreme = 0; } else { animator.currentFreme++; } spriteAnimationUpdate(animator, texCoord); } void spriteAnimationUpdate(SpriteAnimator & animator, float * texCoord) { const int X = 0; const int Y = 1; const int V0 = 0; const int V1 = 2; const int V2 = 4; const int V3 = 6; const float frameWidth = 1.f / animator.columns; const float frameHeight = 1.f / animator.rows; const int row = animator.rows - animator.currentFreme / animator.columns; const int col = animator.currentFreme % animator.columns; texCoord[V0 + X] = frameWidth * col; texCoord[V0 + Y] = frameHeight * row; texCoord[V1 + X] = frameWidth * (col + 1); texCoord[V1 + Y] = frameHeight * row; texCoord[V2 + X] = frameWidth * (col + 1); texCoord[V2 + Y] = frameHeight * (row + 1); texCoord[V3 + X] = frameWidth * col; texCoord[V3 + Y] = frameHeight * (row + 1); } int main() { GLFWwindow* window; if (!glfwInit()) return -1; window = glfwCreateWindow(640, 480, "Simple animated texture with OpenGL", NULL, NULL); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glewInit(); Shader shader = createShader(); SpriteAnimator animator = initSpriteAnimation(6, 6, texCoord); while (!glfwWindowShouldClose(window)) { render(shader); Sleep(1000 / 25); //Sleep(1000); spriteAnimationNextFrame(animator, texCoord); glfwSwapBuffers(window); glfwPollEvents(); } glfwDestroyWindow(window); glfwTerminate(); return 0; }
Source: https://habr.com/ru/post/311346/
All Articles