Skip to content

Commit d10e911

Browse files
committed
add hellotriangle for opengl 4.6
1 parent d71b0d9 commit d10e911

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

gl46core-hellotriangle/main.go

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright 2021 The go-gl Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Renders a red triangle using GLFW 3.3 and OpenGL 4.6 core forward-compatible profile.
6+
package main
7+
8+
import (
9+
"errors"
10+
"fmt"
11+
_ "image/png"
12+
"log"
13+
"runtime"
14+
15+
"github.com/go-gl/gl/v4.6-core/gl"
16+
"github.com/go-gl/glfw/v3.3/glfw"
17+
)
18+
19+
const windowWidth = 800
20+
const windowHeight = 600
21+
22+
func init() {
23+
// GLFW event handling must run on the main OS thread
24+
runtime.LockOSThread()
25+
}
26+
27+
func main() {
28+
if err := glfw.Init(); err != nil {
29+
log.Fatalln("failed to initialize glfw:", err)
30+
}
31+
defer glfw.Terminate()
32+
33+
glfw.WindowHint(glfw.Resizable, glfw.False)
34+
glfw.WindowHint(glfw.ContextVersionMajor, 4)
35+
glfw.WindowHint(glfw.ContextVersionMinor, 1)
36+
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
37+
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
38+
window, err := glfw.CreateWindow(windowWidth, windowHeight, "Hello colorful triangle", nil, nil)
39+
if err != nil {
40+
panic(err)
41+
}
42+
window.MakeContextCurrent()
43+
44+
// Initialize Glow.
45+
if err := gl.Init(); err != nil {
46+
panic(err)
47+
}
48+
49+
version := gl.GoStr(gl.GetString(gl.VERSION))
50+
fmt.Println("OpenGL version", version)
51+
52+
// Compile, link and validate vertex and fragment shaders.
53+
program, err := CompileProgram(vertexShader, fragmentShader)
54+
if err != nil {
55+
panic(err)
56+
}
57+
gl.UseProgram(program)
58+
gl.BindFragDataLocation(program, 0, gl.Str("outputColor\x00"))
59+
60+
// Configure the vertex data
61+
var vao uint32
62+
gl.GenVertexArrays(1, &vao)
63+
gl.BindVertexArray(vao)
64+
65+
// float32 is 4 bytes wide.
66+
const attrSize = 4
67+
var vbo uint32
68+
gl.GenBuffers(1, &vbo)
69+
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
70+
gl.BufferData(gl.ARRAY_BUFFER, attrSize*len(triangleVertices), gl.Ptr(triangleVertices), gl.STATIC_DRAW)
71+
vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00")))
72+
gl.EnableVertexAttribArray(vertAttrib)
73+
74+
// Stride is 2 since our data is 2D.
75+
gl.VertexAttribPointerWithOffset(vertAttrib, 3, gl.FLOAT, false, 2*attrSize, 0)
76+
77+
for !window.ShouldClose() {
78+
gl.Clear(gl.COLOR_BUFFER_BIT)
79+
// gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])
80+
gl.BindVertexArray(vao)
81+
gl.DrawArrays(gl.TRIANGLES, 0, 3)
82+
// Maintenance
83+
window.SwapBuffers()
84+
glfw.PollEvents()
85+
if window.GetKey(glfw.KeyEscape) == glfw.Press {
86+
window.SetShouldClose(true)
87+
}
88+
}
89+
}
90+
91+
var vertexShader string = `
92+
#version 330
93+
in vec3 vert;
94+
95+
void main() {
96+
gl_Position = vec4(vert,1);
97+
}
98+
` + "\x00"
99+
100+
var fragmentShader string = `
101+
#version 330
102+
out vec4 outputColor;
103+
104+
void main() {
105+
outputColor = vec4(1.0,0.0,0.0,1.0);
106+
}
107+
` + "\x00"
108+
109+
var triangleVertices = []float32{
110+
-1.0, -1.0,
111+
1.0, -1.0,
112+
0.0, 1.0,
113+
}
114+
115+
func CompileProgram(vertexSrcCode, fragmentSrcCode string) (program uint32, err error) {
116+
program = gl.CreateProgram()
117+
vid, err := compile(gl.VERTEX_SHADER, vertexSrcCode)
118+
if err != nil {
119+
return 0, fmt.Errorf("vertex shader compile: %w", err)
120+
}
121+
fid, err := compile(gl.FRAGMENT_SHADER, fragmentSrcCode)
122+
if err != nil {
123+
return 0, fmt.Errorf("fragment shader compile: %w", err)
124+
}
125+
gl.AttachShader(program, vid)
126+
gl.AttachShader(program, fid)
127+
gl.LinkProgram(program)
128+
log := ivLog(program, gl.LINK_STATUS, gl.GetProgramiv, gl.GetProgramInfoLog)
129+
if len(log) > 0 {
130+
return 0, fmt.Errorf("link failed: %v", log)
131+
}
132+
// We should technically call DetachShader after linking... https://www.youtube.com/watch?v=71BLZwRGUJE&list=PLlrATfBNZ98foTJPJ_Ev03o2oq3-GGOS2&index=7&ab_channel=TheCherno
133+
gl.ValidateProgram(program)
134+
log = ivLog(program, gl.VALIDATE_STATUS, gl.GetProgramiv, gl.GetProgramInfoLog)
135+
if len(log) > 0 {
136+
return 0, fmt.Errorf("validation failed: %v", log)
137+
}
138+
139+
// We can clean up.
140+
gl.DeleteShader(vid)
141+
gl.DeleteShader(fid)
142+
return program, nil
143+
}
144+
145+
func compile(shaderType uint32, sourceCode string) (uint32, error) {
146+
id := gl.CreateShader(shaderType)
147+
csources, free := gl.Strs(sourceCode)
148+
gl.ShaderSource(id, 1, csources, nil)
149+
free()
150+
gl.CompileShader(id)
151+
152+
// We now check the errors during compile, if there were any.
153+
log := ivLog(id, gl.COMPILE_STATUS, gl.GetShaderiv, gl.GetShaderInfoLog)
154+
if len(log) > 0 {
155+
return 0, errors.New(log)
156+
}
157+
return id, nil
158+
}
159+
160+
// ivLog is a helper function for extracting log data
161+
// from a Shader compilation step or program linking.
162+
//
163+
// log := ivLog(id, gl.COMPILE_STATUS, gl.GetShaderiv, gl.GetShaderInfoLog)
164+
// if len(log) > 0 {
165+
// return 0, errors.New(log)
166+
// }
167+
func ivLog(id, plName uint32, getIV func(program uint32, pname uint32, params *int32), getInfo func(program uint32, bufSize int32, length *int32, infoLog *uint8)) string {
168+
var iv int32
169+
getIV(id, plName, &iv)
170+
if iv == gl.FALSE {
171+
var logLength int32
172+
getIV(id, gl.INFO_LOG_LENGTH, &logLength)
173+
log := make([]byte, logLength)
174+
getInfo(id, logLength, &logLength, &log[0])
175+
return string(log[:len(log)-1]) // we exclude the last null character.
176+
}
177+
return ""
178+
}

0 commit comments

Comments
 (0)