OpenGL glUniform1f not updating vertex shader - c

All the tutorials seem to indicate that I am doing things correctly, the vertex shader works, however it fails to recognize any input changes from the main program through the use of the glUniform1f function. I check glGetError after each line, there are no errors. I check glGetShaderiv and glGetShaderInfoLog, there are no issues. I am testing with OpenGL version 2.1 (unknown profile, but assuming the core profile) as reported by SDL.
#if defined(__WINDOWS__) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__)\
|| defined(__CYGWIN__)
/* Compiling for Windows */
#ifndef __WINDOWS__
#define __WINDOWS__
#endif
#include <windows.h>
#endif/* Predefined Windows macros */
#include <SDL2/SDL.h>
#include <GL/GL.h>
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
//return type not verified
void glGenBuffers();
void glBindBuffer();
void glBufferData();
unsigned int glCreateShader();
void glShaderSource();
void glCompileShader();
void glGetShaderiv();
void glGetShaderInfoLog();
unsigned int glCreateProgram();
void glAttachShader();
void glLinkProgram();
void glGetProgramiv();
void glGetProgramInfoLog();
void glVertexAttribPointer();
void glEnableVertexAttribArray();
void glUseProgram();
void glDeleteShader();
void glGenVertexArrays();
void glBindVertexArray();
GLint glGetUniformLocation();
void glUniform1f();
void glDeleteProgram();
void glDeleteBuffers();
int fixSDLconsole() {
FILE *console = freopen("stdout.txt", "a",stdout);
if (console == NULL) {return errno;}
console = freopen("stdout.txt", "a",stderr);
if (console == NULL) {return errno;}
return 0;
}
void printGLVersionNumber() {
int majorVersion;
int minorVersion;
int profile;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &majorVersion);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minorVersion);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile);
fprintf(stderr,"GL version %d.%d ",majorVersion,minorVersion);
switch (profile) {
case SDL_GL_CONTEXT_PROFILE_CORE: fprintf(stderr,"core (%d)\n",profile);break;
case SDL_GL_CONTEXT_PROFILE_COMPATIBILITY: fprintf(stderr,"compatibility (%d)\n",profile);break;
case SDL_GL_CONTEXT_PROFILE_ES: fprintf(stderr,"E.S. (%d)\n",profile);break;
default: fprintf(stderr, "unknown profile: %d\n",profile);break;
}
return;
}
#define checkGlError(label) {int error = glGetError();if (error != GL_NO_ERROR) {error_at_line(0,0,__FILE__,__LINE__,"error=%d", error);goto label;}}
int main(int argc, char **argv) {
SDL_Window *window = NULL;
SDL_GLContext context = NULL;
GLuint verticesGlIds[] = {0,0};
GLuint vertexShaderGlId = 0;
GLuint shaderProgramGlId = 0;
if (fixSDLconsole()) {
return errno;
}
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
error_at_line(1,0,__FILE__,__LINE__,"Unable to initialize SDL: %s",SDL_GetError());
goto error;
}
printGLVersionNumber();
window = SDL_CreateWindow("Window Title",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,640,SDL_WINDOW_OPENGL);
if (window == NULL) {
error_at_line(0,0,__FILE__,__LINE__,"Could not create window: %s", SDL_GetError());
goto error;
}
context = SDL_GL_CreateContext(window);
if (context == NULL) {
error_at_line(0,0,__FILE__,__LINE__,"Could not create OpenGL context: %s", SDL_GetError());
goto error;
}
glViewport(0,0,640,640);checkGlError(error);
glClearColor(.9f,.9f,.9f,1.f);checkGlError(error);
glEnableClientState(GL_VERTEX_ARRAY);checkGlError(error);
glEnableClientState(GL_COLOR_ARRAY);checkGlError(error);
float vertices[] = {
-.5f,0.f,0.f,
0.f,.5f,0.f,
0.f,-.5f,0.f,
0.f,.5f,0.f,
.5f,.5f,0.f,
0.f,0.f,0.f
};
float colors[] = {
1.f,0.f,0.f,//red
.5f,0.f,0.f,//red
0.f,1.f,0.f,//green
0.f,.5f,0.f,//green
0.f,0.f,1.f,//blue
0.f,0.f,.5f//blue
};
glGenBuffers(2, &verticesGlIds);checkGlError(error);
glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[0]);checkGlError(error);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);checkGlError(error);
glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[1]);checkGlError(error);
glBufferData(GL_ARRAY_BUFFER,sizeof(colors),colors, GL_STATIC_DRAW);checkGlError(error);
char *vertexShader =
"#version 120\n"\
"attribute vec3 aPos;\n"\
"uniform float i;\n"\
"void main() {\n"\
"gl_FrontColor=gl_Color;\n"\
"gl_Position = vec4(aPos.x+i/2,aPos.y,aPos.z,1.0);\n"\
"}\n";
vertexShaderGlId = glCreateShader(GL_VERTEX_SHADER);checkGlError(error);
if (vertexShaderGlId == 0) {error_at_line(0,0,__FILE__,__LINE__,"vertex shader could not be created");goto error;}
glShaderSource(vertexShaderGlId, 1, &vertexShader, NULL);checkGlError(error);
glCompileShader(vertexShaderGlId);checkGlError(error);
{
GLint success;
glGetShaderiv(vertexShaderGlId, GL_COMPILE_STATUS, &success);checkGlError(error);
if (success == GL_FALSE) {
char infoLog[512];
glGetShaderInfoLog(vertexShaderGlId, 512, NULL, infoLog);checkGlError(error);
error_at_line(0,0,__FILE__,__LINE__,"Vertex Shader problem: %s", infoLog);
goto error;
}
}
shaderProgramGlId = glCreateProgram();checkGlError(error);
if (shaderProgramGlId == 0) {error_at_line(0,0,__FILE__,__LINE__,"shader program could not be created");goto error;}
glAttachShader(shaderProgramGlId, vertexShaderGlId);checkGlError(error);
glLinkProgram(shaderProgramGlId);checkGlError(error);
{
int success;
glGetProgramiv(shaderProgramGlId, GL_LINK_STATUS, &success);checkGlError(error);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgramGlId, 512, NULL, infoLog);checkGlError(error);
error_at_line(0,0,__FILE__,__LINE__,"Shader program problem: %s", infoLog);
}
}
glDeleteShader(vertexShaderGlId);checkGlError(error);
GLint iLocation = glGetUniformLocation(shaderProgramGlId, "i");checkGlError(error);
if (iLocation == -1) {error_at_line(0,0,__FILE__,__LINE__,"uniform i not found in shader");goto error;}
error_at_line(0,0,__FILE__,__LINE__,"iLocation: %d", iLocation);
for (int frame = 0; frame < 100; ++frame) {
glClear(GL_COLOR_BUFFER_BIT);checkGlError(error);
glUseProgram(shaderProgramGlId);checkGlError(error);
glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[0]); checkGlError(error);
glVertexPointer(3,GL_FLOAT,0,0); checkGlError(error);
glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[1]); checkGlError(error);
glColorPointer(3,GL_FLOAT,0,0); checkGlError(error);
glUniform1f(iLocation, (float) (frame%2)); checkGlError(error);
glDrawArrays(GL_TRIANGLES, 0,sizeof(vertices)/sizeof(float)/3); checkGlError(error);
glBindBuffer(GL_ARRAY_BUFFER, 0); checkGlError(error);
SDL_GL_SwapWindow(window);
SDL_Delay(100);
}
glDeleteProgram(shaderProgramGlId);
glDeleteShader(vertexShaderGlId);
glDeleteBuffers(sizeof(verticesGlIds)/sizeof(GLuint), verticesGlIds);
SDL_GL_DeleteContext(context);
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
error:
glDeleteProgram(shaderProgramGlId);
glDeleteShader(vertexShaderGlId);
glDeleteBuffers(sizeof(verticesGlIds)/sizeof(GLuint), verticesGlIds);
if (context != NULL) SDL_GL_DeleteContext(context);
if (window != NULL) SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_FAILURE;
}
#if defined(__WINDOWS__)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
char *argv[1] = {(char *) 0};
return main(0, argv);
}
#endif
note that I am not familiar with OpenGL's extension function loading issues and routines such as SDL's SDL_GL_LoadLibrary and SDL_GL_GetProcAddress I just manually define the method signatures at the top of the file and import GL through the linker. I don't expect this to be an issue but it is the only issue, I am aware of, that I haven't looked into, that may be causing my problems.

So you declare the function like this:
void glUniform1f();
By omitting any parameters, the compiler will assume that all arguments are of type int. For most other GL functions, this works by chance, because those arguments are just integer types in most cases anyway, but for glUniform1f, it will mean that the function argument is converted to integer, but the resulting bit-pattern is implicitely re-interpreted as GLfloat by the function since the actual prototype for glUniform1f is something like this
void glUniform1f(int location, GLfloat value);
note that I am not familiar with OpenGL's extension function loading issues and routines such as SDL's SDL_GL_LoadLibrary and SDL_GL_GetProcAddress I just manually define the method signatures at the top of the file and import GL through the linker.
You shouldn't do this. The GL functions you try to access might not even be exported by the library at all. If you do not want to manually deal with loading every function pointer, you can use one of the existing OpenGL loaders.

gl_Position expects Clip-space coordinates, which are a hiper-cube of size [2w,2w,2w,w].
For vec4(x, y, z, w) if any of the [x,y,z] is outside of [-w,w] range, then the vertex is clipped.
The coordinates will be automatically converted by the GPU to NDC-space x/w, y/w, z/w, 1 (aka "perspective division") before the fragment shader.
Your GLSL code gl_Position = vec4(aPos.x+i/2,aPos.y,aPos.z,1.0); uses the uniform i.
You update it by glUniform1f(iLocation, (float) (frame%2));
First issue is frame%2. Only 0 or 1 is passed to the GPU. With your current vertices data, only two pairs of triangles should be drawn.
Second issue is that frame is a value 0 <= frame < 100. So, if you pass frame instead of frame%2, then for most values aPos.x + i/2 will fall outside the Clip space and you will see only the first two triangle-pairs, or parts of them.

Related

vkCreateInsatance segmentation fault

I followed by vulkan tutorial, and i get segfault on vkCreateInstance.
I use arch (btw), and i install vulkan by paru -S vulkan-devel (also linux-firmware and mesa are installed). My CPU is AMD Ryzen 7 2700, and GPU is Radeon RX 580 4GB.
I saw a similar question, but the answer did not solve my problem (and besides, they use C++, not C)
#include <stdio.h>
#include <stdlib.h>
#include <vulkan/vulkan.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
const char* APPLICATION_NAME = "Vulkan Teach";
const uint16_t WIDTH = 800;
const uint16_t HEIGHT = 600;
static GLFWwindow* window;
static VkInstance instance;
void error(char* message, int code) {
fprintf(stderr, "%s (status code: %d)\n", message, code);
exit(code);
}
void initWindow() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, APPLICATION_NAME, NULL, NULL);
}
void mainLoop() {
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}
void createInsance() {
VkApplicationInfo appInfo;
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = APPLICATION_NAME;
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
uint32_t glfwExtensionsCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionsCount);
createInfo.enabledExtensionCount = glfwExtensionsCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
createInfo.enabledLayerCount = 0;
VkResult result = vkCreateInstance(&createInfo, NULL, &instance);
if(result != VK_SUCCESS) {
error("Failed to create vulkan instance.", result);
}
}
void initVulkan() {
createInsance();
}
void cleanup() {
vkDestroyInstance(instance, NULL);
glfwDestroyWindow(window);
glfwTerminate();
}
int main() {
initWindow();
initVulkan();
mainLoop();
cleanup();
return 0;
}
You are most probably passing uninitialized values to your instance creation. This part of the code:
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
Only initializes the sType and pApplicationInfo members of the create info, while other important members such as pNext are uninitialized and as such may contain values that the driver doesn't know how to handle, resulting in the segfault.
So as a general rule for all (Vulkan) structs: Zero initialize like this:
VkInstanceCreateInfo createInfo = {0};

SDL2 confusion with pointers c

I'm trying to program a basic game with SDL2 library and I am getting a little bit confused with a basic concept.
Basically I would like to make a function:
void quit_clean (SDL_Window *window, SDL_Renderer *renderer)
{
if (renderer != NULL)
SDL_DestroyRenderer(renderer);
if (window != NULL)
SDL_DestroyWindow(window);
exit(EXIT_FAILURE);
}
I would call this function each time there is an error so I can free the renderer and the window properly before to quit the program
e.g.
texture = SDL_CreateTextureFromSurface(renderer, tmp);
if(texture==NULL){
printf ("SDL_CreateTextureFromSurface Error: : %s\n", SDL_GetError());
quit_clean (&window, &renderer);
}
Where I am getting confused is if I need to call this function from another function how does it work ?
To be precise I would have:
My main() function where I create my *window and my *renderer
a new my_function() called from main() in which I would among other stuffs create a texture from a surface and test errors
and finally my quit_clean() function called from my_function() in case of error.
The way I see it, in order to pass my window and my renderer from main() to quit_clean() using my_function() the prototypes would be then:
void my_function (SDL_Window **window, SDL_Renderer **renderer);
void quit_clean (SDL_Window ***window, SDL_Renderer ***renderer);
Am I correct or not?
If yes then how could I call this function from main() if needed.
If I call "quit_clean (&window, &renderer);" from my main() the types are not correct anymore then.
Or maybe I could create pointers from window and renderer and pass those pointers to quit_clean(). I don't know I'm confused, I'm not sure if my thought process is correct.
Do you have any tips for this kind of situation?
You don't need the double pointer as arguments to your functions:
int my_function (SDL_Window *window, SDL_Renderer *renderer);
int quit_clean (SDL_Window *window, SDL_Renderer *renderer);
As you might have noticed, i've added a return type (int), because every function should return a result, indicating success or failure.
Secondly, it would be better not to call the quit_clean function from other functions, instead, if you encounter an error in for e.g. my_function, return an error and call the quit_clean function in the main function.
Like this:
int main()
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
window = SDL_CreateWindow(...);
if (window) {
renderer = SDL_CreateRenderer(window, ...);
if (renderer) {
int err = my_function(window, renderer);
if (!err) { //success: 0, error: -1
//do what is needed to be done
}
}
}
//finally clean up,
//no matter the case (either due to error or program termination)
quit_clean(window, renderer);
return 0;
}
In the quit_clean function you have to check the passed arguments (although i think that SDL checks them too, but better than sorry):
int quit_clean (SDL_Window *window, SDL_Renderer *renderer)
{
//other cleanup first
//finally
if (renderer != NULL)
SDL_DestroyRenderer(renderer);
if (window != NULL)
SDL_DestroyWindow(window);
SDL_Quit();
}
And for clarity an example of my_function:
int my_function (SDL_Window *window, SDL_Renderer *renderer)
{
if (some_condition_does_not_hold)
return -1;
//do your stuff
//never call quit_clean if something goes wrong, return either -1 or
//some other (previously defined) negative error number
//finally
return 0; //success
}

C, SDL: error: cannot convert 'SDL_Surface*' to 'SDL_Surface* (*)[15]

so I'm working on a code for filling a screen with a table of surfaces; here's the code:
main.c
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <SDL/SDL.h>
#include <SDL_image.h>
#include "maploader.h"
#define W 510
#define H 510
#define SIZE 34
void pause();
int main ( int argc, char** argv )
{
SDL_Surface *screen = NULL;
SDL_Surface *surfaces[15][15];
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(W, H, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_WM_SetCaption("demon game", NULL);
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
mapload(screen, surfaces[15][15], NULL);
SDL_Flip(screen);
pause();
SDL_QUIT;
return EXIT_SUCCESS;
}
void pause()
{
int continuer = 1;
SDL_Event event;
while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
}
}
}
maploader.c
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <SDL/SDL.h>
#include <SDL_image.h>
#define W 510
#define H 510
#define SIZE 34
SDL_Surface *surfaces[15][15];
void mapload(SDL_Surface *screen, SDL_Surface *surfaces[][15], int lvl)
{
FILE *level = NULL;
char elements[125];
int i, j, k = 0;
SDL_Rect elementposition = {0,0};
level = fopen("level.txt", "r");
if (level == NULL)
{
exit(0);
}
fgets(elements, 125, level);
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
for (i=0; i<15; i++)
{
for (j=0; j<15; j++)
{
if (elements[k] == "0")
{
surfaces[i][j] = IMG_Load("mur.jpg");
}
else if (elements[k] == "1")
{
surfaces[i][j] = IMG_Load("caisse.jpg");
}
else if (elements[k] == "2")
{
surfaces[i][j] = IMG_Load("objectif.png");
}
else
{
surfaces[i][j] = NULL;
}
k++;
}
}
for (i=0; i<15; i++)
{
for (j=0; j<15; j++)
{
SDL_BlitSurface(surfaces[i][j], NULL, screen, &elementposition);
elementposition.x += SIZE;
}
elementposition.y += SIZE;
}
}
the only error I get from compiling is the following: "cannot convert 'SDL_Surface*' to 'SDL_Surface* ()[15]' for argument '2' to 'void mapload(SDL_Surface, SDL_Surface* (*)[15], int)'|"
apparently, the error is initialized from the second argument of the mapload function, but I don't have a clear idea about what exactly is wrong. any ideas, please?
This,
mapload(screen, surfaces[15][15], NULL);
should be
mapload(screen, surfaces, NULL);
But now you should ask yourself, if you didn't know that then probably,
The signature of void mapload(SDL_Surface *screen, SDL_Surface *surfaces[][15], int lvl) is altogether wrong.
You need to study what are arrays in c and their relation to pointers.
Note that surfaces[15][15] means the 16th element of the 16th array of pointers, none of which exists because you only allocated 15 of each. So you need to understand arrays in c, how they are allocated and how you can have a dynamic array.
Also, the fact that you tell a c compiler that a function is expecting an array is not very relevant inside such function, so the syntax SDL_Surface *surfaces[][15] seems strange to a c programmer.
And finally, since surfaces is a global variable you don't need to pass it as a parameter, but then you should ask yourself, should it be a global variable?

Return statement being ignored

For future readers
Don't code tired. It turns you into a wee bit of a dink.
My problem was that I had two separate outputs that appeared to collide with one another. One was beyond a return statement, so it was alarming that the code was being executed at all. However, it had not occurred to me to use Visual Studio's search function to check every other file to see if there was another reason I was getting output. To my knowledge at that time, there was only a single call to the LoadGLSLFromFile function, when there was actually two.
The results were extreme frustration on my end because I was positive that there was no other calls to that function, and that somehow there must be optimizations to my code that's either messing up the ordering of the function, or, the return statement is not functioning as it should (for whatever reason).
If you are going to post a question, I urge you to re-evaluate what is deemed as "relevant" code. You are here because you're not seeing something that others can, after all.
If you read the comments of this, you will see that StoryTeller was trying to get it through to me that what I was assuming was happening was indeed not possible, and that my methods of debugging were incorrect. StoryTeller, if you're reading this, I do sincerely apologize.
===============================
EDIT 2: Note that the issue I am having is that the function is not returning when I told it to. It continues execution beyond the return, inside the same function, until it hits a second one.
So, I am really lost as to why this is occurring, but this is my code. So, usually what I do is I check for critical failures, and if there is a serious issue, I return a known "error" value. However, the return is being ignored in multiple places, and the code is executing in the wrong order. (see the second image for the wrong order)
EDIT:
My problem is that the code is executing beyond the return statements.
#include "Loader.h"
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#include <GLFW/glfw3.h>
static const GLchar * VSource[] = {
"#version 450 core\n"
"layout (location = 0) in vec4 offset;\n"
"layout (location = 1) in vec4 color;\n"
"out VS_OUT {\n"
" vec4 color;"
"} vs_out;\n"
"void main(void)\n"
"{\n"
" const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0),\n"
" vec4(-0.25, -0.25, 0.5, 1.0),\n"
" vec4(0.25, 0.25, 0.5, 1.0));\n"
" gl_Position = vertices[gl_VertexID] + offset;\n"
" vs_out.color = color;"
"}\n"
};
static const GLchar* FSource[] = {
"#version 450 core\n"
"in VS_OUT {\n"
" vec4 color;\n"
"} fs_in;\n"
"out vec4 color;\n"
"void main(void)\n"
"{\n"
" color = fs_in.color;\n"
"}\n"
};
static const GLchar* TControlSource[] = {
"#version 450 core\n"
"layout (vertices = 3) out;\n"
"void main(void) {\n"
" if(gl_InvocationID == 0) {\n"
" gl_TessLevelInner[0] = 5.0;\n"
" gl_TessLevelOuter[0] = 5.0;\n"
" gl_TessLevelOuter[1] = 5.0;\n"
" gl_TessLevelOuter[2] = 5.0;\n"
" }\n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
"}"
};
GLuint LoadAllShaders() {
LoadGLSLFromFile("glsl", GL_VERTEX_SHADER);
GLuint VShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VShader, 1, VSource, NULL);
glCompileShader(VShader);
LogCompileStatus(VShader, "VShader");
GLuint FShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FShader, 1, FSource, NULL);
glCompileShader(FShader);
LogCompileStatus(FShader, "FShader");
GLuint TShader = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(TShader, 1, TControlSource, NULL);
glCompileShader(TShader);
LogCompileStatus(TShader, "Tessellation Shader");
GLuint Program = glCreateProgram();
glAttachShader(Program, VShader);
glAttachShader(Program, FShader);
glAttachShader(Program, TShader);
glLinkProgram(Program);
glDeleteShader(VShader);
glDeleteShader(FShader);
glDeleteShader(TShader);
return Program;
}
void LogCompileStatus(GLuint Shader, char* ShaderName) {
// Checking compile status of VShader
if (ShaderName == NULL || sizeof(ShaderName) == 0)
ShaderName = ("Unnamed Shader with ID: %i" + (char)&Shader);
GLuint ShaderSuccess = GL_FALSE;
glGetShaderiv(Shader, GL_COMPILE_STATUS, &ShaderSuccess);
if (ShaderSuccess == GL_TRUE)
printf("%s successfully compiled\n", ShaderName);
else {
GLint LogLength;
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &LogLength);
char* buffer = (char*)malloc(LogLength);
glGetShaderInfoLog(Shader, LogLength, NULL, buffer);
printf("%s failed to compile.\n%s\n", ShaderName, buffer);
free(buffer);
}
}
GLuint LoadGLSLFromFile(char* location, GLenum ShaderType) {
if (sizeof(location) < 6 || strstr(location, ".glsl") == NULL) {
fprintf(stderr, "Attempted to load invalid file.\n");
return 0;
}
switch (ShaderType) {
case(GL_COMPUTE_SHADER):
case(GL_VERTEX_SHADER):
case(GL_TESS_CONTROL_SHADER):
case(GL_TESS_EVALUATION_SHADER):
case(GL_GEOMETRY_SHADER):
case(GL_FRAGMENT_SHADER):
break;
default:
fprintf(stderr, "Invalid Shadertype\n");
break;
}
FILE* shaderFile = fopen(location, "r");
if (shaderFile == NULL) {
fprintf(stderr, "Wurbulgurb\n");
return 0;
}
size_t bufferSize = fseek(shaderFile, 0, SEEK_END);
printf("File Buffer size: %i\n", (int)bufferSize);
fclose(shaderFile);
/*
glShaderSource(shd, 1, VSource, NULL);
glCompileShader(shd);
LogCompileStatus(shd, "VShader");
*/
return 1;
}
The main file:
#include <stdio.h>
#include <stdlib.h>
#include <GL\glew.h>
#include <GL\GL.h>
#include <GL\GLU.h>
#include <GL\wglew.h>
#include <GLFW\glfw3.h>
#include "Loader.h"
#define CL_BUFFER (GLfloat[4]) { 0.3f, 0.3f, 0.3f, 1.0f }
int main(void);
void err(int error, const char * msg);
void keypress(GLFWwindow *window, int key, int scancode, int action, int mods);
static GLfloat attrib[] = { 0.0f, 0.0f, 0.5f, 1.0f };
int main(void) {
if (!glfwInit())
return -1;
GLFWwindow *window = glfwCreateWindow(1024, 768, "Fididdler", NULL, NULL);
glfwWindowHint(GLFW_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_VERSION_MINOR, 5);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
if (window == NULL)
return -1;
LoadGLSLFromFile("./Condoms.glsl", GL_VERTEX_SHADER);
glfwSetErrorCallback(err);
glfwSetKeyCallback(window, keypress);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return -1;
printf("GL Version String: %s \n", glGetString(GL_VERSION));
GLuint RProg = LoadAllShaders();
GLuint VAO;
glCreateVertexArrays(1, &VAO);
glBindVertexArray(VAO);
printf("Loading complete");
while (!glfwWindowShouldClose(window)) {
glClearBufferfv(GL_COLOR, 0, CL_BUFFER);
glUseProgram(RProg);
glVertexAttrib4fv(0, attrib);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* End drawing logic*/
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteProgram(RProg);
glfwTerminate();
return 1;
}
void err(int error, const char * msg) {
printf("Error: %s", msg);
}
void keypress(GLFWwindow *window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
switch (key) {
case(GLFW_KEY_W):
attrib[1] += 0.01f;
printf("W pressed");
break;
case(GLFW_KEY_S):
attrib[1] -= 0.01f;
printf("S pressed");
break;
}
switch (key) {
case(GLFW_KEY_A):
attrib[0] -= 0.01f;
printf("A pressed");
break;
case(GLFW_KEY_D):
attrib[0] += 0.01f;
printf("D pressed");
break;
}
}
This is the console output for LoadGLSLFromFile("TessControl.glsl", GL_VERTEX_SHADER);. Note: Line 3 should not happen, as there was a return statement prior to it.
This is the console output for LoadGLSLFromFile("glsl", GL_VERTEX_SHADER);
Note: Line 3 should not happen, as there was a return statement prior to it.
There's a return statement specifically blocking further execution, and yet it still executes. I am quite puzzled with this behavior because as far as I am aware, return means "immediately go back to the line that called you".
Any and all assistance would be greatly appreciated.
You say that the return value is being ignored. That is exactly what your code is doing:
GLuint LoadAllShaders() {
// return value is ignored
LoadGLSLFromFile("glsl", GL_VERTEX_SHADER);
GLuint VShader = glCreateShader(GL_VERTEX_SHADER);
Because you don't check the return value, there is nothing to prevent your code from continuing.
Perhaps you're confusing return with exit(). The return statement returns a value from a function so that the calling function can decide how to proceed. The exit function causes the program to terminate, with the passed in value being the return value of your program.
If you want your program to quit, you should use exit. If not, then you need to check the return value in the above code and act accordingly.
EDIT:
This is why a MCVE is so important.
After posting your main code, the issue is that you're calling LoadGLSLFromFile twice. You first call it directly from main. Then main calls LoadAllShaders, which calls LoadGLSLFromFile again.
So "Wurbulgurb" prints on the first call, while either "Attempted to load invalid file" or "File Buffer size" is printed on the second call.

I am trying to initialize an SDL_Window in a function but it always fails unless I define SDL_Window*win; as a global variable

I am trying to initialize an SDL_Window in a function but it always fails unless I define SDL_Window*win; as a global variable. Here is the code:
#include<SDL2/SDL.h>
#include<stdio.h>
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
SDL_Surface*Init(SDL_Window*win,char*title,int x,int y,int w,int h,Uint32 flags);
int main(int argc,char**argv){
SDL_Surface *screen=NULL;
SDL_Window*win=NULL;
screen=Init(win,"SDL_Test",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0xFF,0x00,0x00));
SDL_UpdateWindowSurface(win);
SDL_Delay(2000);
}
SDL_Surface*Init(SDL_Window*win,
char*title,
int x,
int y,
int w,
int h,
Uint32 flags){
SDL_Surface*temp=NULL;
if(SDL_Init(SDL_INIT_EVERYTHING)){
printf("\nError : %s",SDL_GetError());
SDL_ClearError();
return NULL;
}
win=SDL_CreateWindow(title,x,6,w,h,flags);
if(!win){
printf("\nError: %s",SDL_GetError());
SDL_ClearError();
return NULL;
}
temp=SDL_GetWindowSurface(win);
if(!temp){
printf("\nError: %s",SDL_GetError());
SDL_ClearError();
return NULL;
}
return temp;
}
If I declare SDL_Window*win as a global variable it shows a red screen(as it should) but if
I define SDL_Window*win in main() and pass it to Init() it show a white screen(error?).
You are not updating win in the main function. In c you pass variables by value and if you change the value of a pointer ( or win in your case ) the change will not happen outside the function.
The shortest ( but not the best ) solution would be to return window pointer win and then get the surface with SDL_GetWindowSurface(win)

Resources