ModernGL basics: compile shader

I’m getting confused by ModernGL API. It would due to

  1. i’m new to using ccall and pointer in julia
  2. i’m new to opengl

i try some code found in this repo, specifically the simplest part: triangle

const vert_source = """
#version 410 core
in vec3 vp;
void main(void)
    gl_Position = vec4(vp, 1.0);
vert_shader = glCreateShader(GL_VERTEX_SHADER)

# from opengl api, the last argument would be pointer to a GLint 
# telling the length of the each source code 
# while GLint == Int32
# why C_NULL works here 
glShaderSource(vert_shader, 1, Ptr{GLchar}[pointer(vert_source)], C_NULL)

# some similar C_NULL usage seen in that script 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, C_NULL) 
# what if i want to specify the offset, what should replace C_NULL

and the second question is

# given i've compiled the shader 
# normally you should check GL_COMPILE_STATUS 
status = Int32[-1]
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, pointer(status))    # is this the right call 
# while checking status, status hasn't changed at all 
# and i think what about this 
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, status)
# still silence 

# then i try this 
status = Int32(-1)
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, status)     # this does not look right to me
# and checking status, nothing happens

# and this is the definition of glGetShaderiv
@glfunc glGetShaderiv(shader::GLuint, pname::GLenum, params::Ptr{GLint})::Cvoid

# so what should be the right call 

I feel that these are stupid questions and simple search would resolve them, e.g reading doc and source. But please someone give me the pill and call me stupid afterwards

i saw this

# print errors in shader compilation
function shader_info_log(shader::GLuint)
    max_length = GLint(0)
    @c glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length)
    actual_length = GLsizei(0)
    log = Vector{GLchar}(undef, max_length)
    @c glGetShaderInfoLog(shader, max_length, &actual_length, log)
    @info "shader info log for GL index $shader: $(String(log))"

and now i want to delete the post

but what is &max_length though

void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);

The last argument is a pointer and C_NULL is Ptr{Nothing} @0x0000000000000000, so it’s ok to let ccall do the auto-conversion.

status = Int32[-1]
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, pointer(status))

This should be:

status_ref = Ref{GLint](-1)
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, status_ref)
status = status_ref[]
julia> @macroexpand @c glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length)
    var"##cref#266" = Ref(max_length)
    var"##cref_ret#267" = glGetShaderiv(shader, GL_INFO_LOG_LENGTH, var"##cref#266")
    max_length = var"##cref#266"[]

The @c macro is a syntax sugar for doing the above ref/deref stuff.

i was asking how opengl figure out the length since we give no info

If length is NULL , each string is assumed to be null terminated.

When passed as a ccall argument (either as a Ptr or Ref type), a Ref object will be
converted to a native pointer to the data it references. For most T, or when
converted to a Ptr{Cvoid}, this is a pointer to the object data. When T is an isbits
type, this value may be safely mutated, otherwise mutation is strictly undefined

make sense now. Thank you :sweat_smile: