func (glr *GlRenderer) initScreen() { var err error glr.program, err = createScreenShader() if err != nil { panic(err) } gl.UseProgram(glr.program) projection := mgl32.Ortho2D(-1, 1, 1, -1) projectionUniform := gl.GetUniformLocation(glr.program, gl.Str("projection\x00")) gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) textureUniform := gl.GetUniformLocation(glr.program, gl.Str("tex\x00")) gl.Uniform1i(textureUniform, 0) glr.texture = createScreenTexture(glr.width, glr.height) gl.GenVertexArrays(1, &glr.vao) gl.BindVertexArray(glr.vao) var quadVertices = []float32{ // X, Y, Z, U, V 1.0, -1.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, } var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(quadVertices)*4, gl.Ptr(quadVertices), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(glr.program, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) texCoordAttrib := uint32(gl.GetAttribLocation(glr.program, gl.Str("vertTexCoord\x00"))) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) gl.Enable(gl.DEPTH_TEST) gl.ClearColor(1.0, 1.0, 1.0, 1.0) }
func makeResources() *gResources { r := gResources{ vertexBuffer1: makeBuffer(gl.ARRAY_BUFFER, gl.Ptr(gVertexBufferData1), 4*len(gVertexBufferData1)), elementBuffer1: makeBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.Ptr(gElementBufferData1), 4*len(gElementBufferData1)), vertexBuffer2: makeBuffer(gl.ARRAY_BUFFER, gl.Ptr(gVertexBufferData2), 4*len(gVertexBufferData2)), elementBuffer2: makeBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.Ptr(gElementBufferData2), 4*len(gElementBufferData2)), colorBuffer2: makeBuffer(gl.ARRAY_BUFFER, gl.Ptr(gColorBufferData2), 4*len(gColorBufferData2)), } r.vertexShader1 = makeShader(gl.VERTEX_SHADER, vertex_glsl1) r.fragmentShader1 = makeShader(gl.FRAGMENT_SHADER, fragment_glsl1) r.program1 = makeProgram(r.vertexShader1, r.fragmentShader1) r.vertexShader2 = makeShader(gl.VERTEX_SHADER, vertex_glsl2) r.fragmentShader2 = makeShader(gl.FRAGMENT_SHADER, fragment_glsl2) r.program2 = makeProgram(r.vertexShader2, r.fragmentShader2) r.uniforms2.xmul = gl.GetUniformLocation(r.program2, gl.Str("xmul\x00")) r.uniforms2.ymul = gl.GetUniformLocation(r.program2, gl.Str("ymul\x00")) r.uniforms2.sin = gl.GetUniformLocation(r.program2, gl.Str("sin\x00")) r.uniforms2.cos = gl.GetUniformLocation(r.program2, gl.Str("cos\x00")) r.attributes1.position = gl.GetAttribLocation(r.program1, gl.Str("position\x00")) r.attributes2.position = gl.GetAttribLocation(r.program2, gl.Str("position\x00")) r.attributes2.color = gl.GetAttribLocation(r.program2, gl.Str("vertexColor\x00")) // circle gColorBufferData3 := make([]float32, 0, 126*3) gVertexBufferData3 := make([]float32, 0, 126*2) gElementBufferData3 := make([]uint32, 0, 126) r.len3 = 0 for i := float64(0); i < 2*math.Pi; i += .05 { rd, g, b := hsb2rgb(float32(i/(2*math.Pi)), 1, 1) gColorBufferData3 = append(gColorBufferData3, rd, g, b) gVertexBufferData3 = append(gVertexBufferData3, float32(math.Sin(i)), float32(math.Cos(i))) gElementBufferData3 = append(gElementBufferData3, uint32(r.len3)) r.len3++ } r.vertexBuffer3 = makeBuffer(gl.ARRAY_BUFFER, gl.Ptr(gVertexBufferData3), 4*len(gVertexBufferData3)) r.elementBuffer3 = makeBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.Ptr(gElementBufferData3), 4*len(gElementBufferData3)) r.colorBuffer3 = makeBuffer(gl.ARRAY_BUFFER, gl.Ptr(gColorBufferData3), 4*len(gColorBufferData3)) return &r }
func makeResources() *gResources { r := gResources{ vertexBuffer: makeBuffer(gl.ARRAY_BUFFER, gl.Ptr(gVertexBufferData), 4*len(gVertexBufferData)), elementBuffer: makeBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.Ptr(gElementBufferData), 4*len(gElementBufferData)), } r.textures[0] = makeTexture("hello1.png") r.textures[1] = makeTexture("hello2.png") r.vertexShader = makeShader(gl.VERTEX_SHADER, vertex_glsl) r.fragmentShader = makeShader(gl.FRAGMENT_SHADER, fragment_glsl) r.program = makeProgram(r.vertexShader, r.fragmentShader) r.uniforms.fadeFactor = gl.GetUniformLocation(r.program, gl.Str("fade_factor\x00")) r.uniforms.textures[0] = gl.GetUniformLocation(r.program, gl.Str("textures[0]\x00")) r.uniforms.textures[1] = gl.GetUniformLocation(r.program, gl.Str("textures[1]\x00")) r.attributes.position = gl.GetAttribLocation(r.program, gl.Str("position\x00")) return &r }
func (objectLoader *WavefrontObject) DrawObject(shaderProgram uint32) { for _, object := range objectLoader.Objects { // Reads the uniform Locations modelUniform := gl.GetUniformLocation(shaderProgram, gl.Str("model\x00")) ambientUniform := gl.GetUniformLocation(shaderProgram, gl.Str("ambient\x00")) diffuseUniform := gl.GetUniformLocation(shaderProgram, gl.Str("diffuse\x00")) specularUniform := gl.GetUniformLocation(shaderProgram, gl.Str("specular\x00")) emissiveUniform := gl.GetUniformLocation(shaderProgram, gl.Str("emissive\x00")) // Send our uniforms variables to the currently bound shader if object.Material != nil { gl.Uniform4f(ambientUniform, object.Material.KaR, object.Material.KaG, object.Material.KaB, object.Material.Tr) // Ambient colour. gl.Uniform4f(diffuseUniform, object.Material.KdR, object.Material.KdG, object.Material.KdB, object.Material.Tr) // Diffuse colour. gl.Uniform4f(specularUniform, object.Material.KsR, object.Material.KsG, object.Material.KsB, object.Material.Tr) // Specular colour. gl.Uniform4f(emissiveUniform, object.Material.KeR, object.Material.KeG, object.Material.KeB, object.Material.Tr) // Emissive colour. if object.Material.Texture != 0 { textureUniform := gl.GetUniformLocation(shaderProgram, gl.Str("DiffuseTextureSampler\x00")) gl.Uniform1i(textureUniform, 0) normalTextureUniform := gl.GetUniformLocation(shaderProgram, gl.Str("NormalTextureSampler\x00")) gl.Uniform1i(normalTextureUniform, 1) specularTextureUniform := gl.GetUniformLocation(shaderProgram, gl.Str("SpecularTextureSampler\x00")) gl.Uniform1i(specularTextureUniform, 2) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, object.Material.Texture) gl.ActiveTexture(gl.TEXTURE1) gl.BindTexture(gl.TEXTURE_2D, object.Material.NormalMap) gl.ActiveTexture(gl.TEXTURE2) gl.BindTexture(gl.TEXTURE_2D, object.Material.SpecularMap) } if object.Material.Tr < 1.0 { // Enables Transparencies gl.Enable(gl.BLEND) // gl.BlendFunc(gl.SRC_COLOR, gl.ONE) // gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) } } // Geometry var size int32 // Used to get the byte size of the element (vertex index) array gl.UniformMatrix4fv(modelUniform, 1, false, &object.Model[0]) // Get the vertices uniform position verticesUniform := uint32(gl.GetAttribLocation(shaderProgram, gl.Str("position\x00"))) normalsUniform := uint32(gl.GetAttribLocation(shaderProgram, gl.Str("normal\x00"))) textureCoordinatesUniform := uint32(gl.GetAttribLocation(shaderProgram, gl.Str("texcoord\x00"))) // Describe our vertices array to OpenGL (it can't guess its format automatically) gl.BindBuffer(gl.ARRAY_BUFFER, object.VertexBufferObjectVertices) gl.VertexAttribPointer( verticesUniform, // attribute index 3, // number of elements per vertex, here (x,y,z) gl.FLOAT, // the type of each element false, // take our values as-is 0, // no extra data between each position nil, // offset of first element ) gl.EnableVertexAttribArray(normalsUniform) gl.BindBuffer(gl.ARRAY_BUFFER, object.VertexBufferObjectNormals) gl.VertexAttribPointer( normalsUniform, // attribute 3, // number of elements per vertex, here (x,y,z) gl.FLOAT, // the type of each element false, // take our values as-is 0, // no extra data between each position nil, // offset of first element ) gl.EnableVertexAttribArray(textureCoordinatesUniform) gl.BindBuffer(gl.ARRAY_BUFFER, object.VertexBufferObjectTextureCoords) gl.VertexAttribPointer( textureCoordinatesUniform, // attribute 2, // number of elements per vertex, here (u,v) gl.FLOAT, // the type of each element false, // take our values as-is 0, // no extra data between each position nil, // offset of first element ) size = int32(len(object.Vertex)) gl.PointSize(3.0) // Enable this line to show model in wireframe switch objectLoader.DrawMode { case 1: gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) default: gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL) } gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.VertexBufferObjectFaces) gl.GetBufferParameteriv(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE, &size) gl.DrawElements(gl.TRIANGLES, int32(len(object.Faces)), gl.UNSIGNED_SHORT, nil) // gl.DrawElements(gl.POINTS, int32(len(object.Faces)), gl.UNSIGNED_SHORT, nil) // Disables transparencies gl.Disable(gl.BLEND) } }
/* Enable vertex attributes and draw object Could improve efficiency by moving the vertex attribute pointer functions to the create object but this method is more general This code is almost untouched fomr the tutorial code except that I changed the number of elements per vertex from 4 to 3*/ func (terrain *Terrain) DrawObject(shaderProgram uint32) { toneUniform := gl.GetAttribLocation(shaderProgram, gl.Str("tone\x00")) gl.Uniform4f(toneUniform, terrain.ColorTone.X(), terrain.ColorTone.Y(), terrain.ColorTone.Z(), terrain.ColorTone.W()) // gl.Uniform4f(toneUniform, 0.0, 1.0, 0.5, 1.0) // gl.Uniform4fv(toneUniform, 1, &terrain.ColorTone[0]) // Reads the uniform Locations modelUniform := gl.GetUniformLocation(shaderProgram, gl.Str("model\x00")) // Send our uniforms variables to the currently bound shader gl.UniformMatrix4fv(modelUniform, 1, false, &terrain.Model[0]) // Get the vertices uniform position verticesUniform := uint32(gl.GetAttribLocation(shaderProgram, gl.Str("position\x00"))) normalsUniform := uint32(gl.GetAttribLocation(shaderProgram, gl.Str("normal\x00"))) colorsUniform := uint32(gl.GetAttribLocation(shaderProgram, gl.Str("colour\x00"))) // Describe our vertices array to OpenGL (it can't guess its format automatically) gl.EnableVertexAttribArray(verticesUniform) gl.BindBuffer(gl.ARRAY_BUFFER, terrain.VBOVertices) gl.VertexAttribPointer( verticesUniform, // attribute index 3, // number of elements per vertex, here (x,y,z) gl.FLOAT, // the type of each element false, // take our values as-is 0, // no extra data between each position nil, // offset of first element ) gl.EnableVertexAttribArray(normalsUniform) gl.BindBuffer(gl.ARRAY_BUFFER, terrain.VBONormals) gl.VertexAttribPointer( normalsUniform, // attribute 3, // number of elements per vertex, here (x,y,z) gl.FLOAT, // the type of each element false, // take our values as-is 0, // no extra data between each position nil, // offset of first element ) gl.EnableVertexAttribArray(colorsUniform) gl.BindBuffer(gl.ARRAY_BUFFER, terrain.VBOColors) gl.VertexAttribPointer( colorsUniform, // attribute 3, // number of elements per vertex, here (x,y,z) gl.FLOAT, // the type of each element false, // take our values as-is 0, // no extra data between each position nil, // offset of first element ) size := int32(len(terrain.Indices)) gl.PointSize(3.0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, terrain.VBOIndices) gl.GetBufferParameteriv(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE, &size) // Enable this line to show model in wireframe switch terrain.DrawMode { case 1: gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) case 2: gl.DrawArrays(gl.POINTS, 0, int32(len(terrain.Vertices))) // gl.DrawElements(gl.POINTS, int32(len(terrain.Indices)), gl.UNSIGNED_SHORT, nil) return default: gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL) } var location int = 0 /* Draw the triangle strips */ for i := uint32(0); i < terrain.XSize-1; i++ { location = SizeOfUint16 * int(i*terrain.ZSize*2) gl.DrawElements(gl.TRIANGLE_STRIP, int32(terrain.ZSize*2), gl.UNSIGNED_SHORT, gl.PtrOffset(location)) } // gl.DrawElements( // gl.TRIANGLE_STRIP, // len(terrain.Indices), // gl.UNSIGNED_SHORT, // nil, // ) }
func createProgram(vertexShaderFile, fragmentShaderFile string, uniforms, attributes []string) (*Shader, error) { // Configure the vertex and fragment shaders vertexShaderSource, err := ioutil.ReadFile(vertexShaderFile) vertexShaderSource = append(vertexShaderSource, 0x00) fragmentShaderSource, err := ioutil.ReadFile(fragmentShaderFile) fragmentShaderSource = append(fragmentShaderSource, 0x00) vertexShader, err := compileShader(string(vertexShaderSource), gl.VERTEX_SHADER) if err != nil { return nil, err } fragmentShader, err := compileShader(string(fragmentShaderSource), gl.FRAGMENT_SHADER) if err != nil { return nil, err } program := gl.CreateProgram() gl.AttachShader(program, vertexShader) gl.AttachShader(program, fragmentShader) gl.LinkProgram(program) var status int32 gl.GetProgramiv(program, gl.LINK_STATUS, &status) if status == gl.FALSE { var logLength int32 gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &logLength) log := strings.Repeat("\x00", int(logLength+1)) gl.GetProgramInfoLog(program, logLength, nil, gl.Str(log)) return nil, fmt.Errorf("failed to link program: %v", log) } gl.DeleteShader(vertexShader) gl.DeleteShader(fragmentShader) gl.UseProgram(program) programUniforms := make(map[string]int32) for _, uniformName := range uniforms { if uniformName != "" { glstr := gl.Str(uniformName + "\x00") programUniforms[uniformName] = gl.GetUniformLocation(program, glstr) } } programAttributes := make(map[string]uint32) for _, attribName := range attributes { if attribName != "" { glstr := gl.Str(attribName + "\x00") programAttributes[attribName] = uint32(gl.GetAttribLocation(program, glstr)) } } return &Shader{ program: program, uniforms: programUniforms, attributes: programAttributes, }, nil }