Home > OS >  C Preprocessor Stringify enter\newline characters
C Preprocessor Stringify enter\newline characters

Time:10-23

So like many that have dealt with OpenGL Shaders in the past being able to write them without an extra program to convert them into a string has always been a want. So what I am looking for is a way to replace enter presses\newline characters in the source code with "\n" for example:

const char *sShaderSrc =
ConvertTextToString(
#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

uniform mat4 mModel;
uniform mat3 mNormal;
uniform mat4 mViewProj;

varying vec3 vNormal;

void main()
{
   gl_Position = (mViewProj *mModel) * vec4(aPos,1.0) ;
   vNormal =  mNormal*aNormal;
}
)
;

and then the preprocessor would convert it into

const char *sShaderSrc =
"#version 330 core\n\nlayout (location = 0) in vec3 aPos;\nlayout (location = 1) in vec3 aNormal;\n\nuniform mat4 mModel;\nuniform mat3 mNormal;\nuniform mat4 mViewProj;\n\nvarying vec3 vNormal;\n\nvoid main()\n{\n   gl_Position = (mViewProj *mModel) * vec4(aPos,1.0);\n   vNormal =  mNormal*aNormal;\n}\n"
;

that way if OpenGL gives errors when compiling then I get shader line numbers in the error message.

Help would be much appreciated. The only edge case I could think of is also dealing with the case if the text editior inserts "\r\n" or "\n".

I have tried

#define RAWSTRINGIFY(x) R#x

//then you do
RAWSTRINGIFY((
 //glsl code here...
))

but doesn't work the straight insertion

CodePudding user response:

A Macro Solution (and why it doesn't work for your purpose)

This can be implemented as a variadic macro so that it actually compiles.

#define ConvertTextToString(...) #__VA_ARGS__

Unfortunately, there are two problems preventing this from being useful in the scenario.

  1. It still doesn't preserve the newlines, as the newlines are not passed to the macro. Macro expansion is done after tokenization, which means that by the time a macro is expanded, all the newlines are already gone. See C preprocessor stringification that preserves newlines?
  2. The #version 330 core is seen by the compiler as a preprocessor directive, which causes errors like this. There's no solution around this.
main.cpp:6:2: error: invalid preprocessing directive
#version 330 core

Using Raw String Literals

A solution to your intended use case (i.e. multiline string literals) is to use raw string literals in C . For example,

const char* shaderSrc = R""""(
#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
// ...
)"""";
  • Related