Skip to content

Commit f5f0ae5

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

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

gl46core-hellotriangle/__debug_bin

3.59 MB
Binary file not shown.

gl46core-hellotriangle/main.go

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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.BindVertexArray(vao)
80+
gl.DrawArrays(gl.TRIANGLES, 0, 3)
81+
// Maintenance
82+
window.SwapBuffers()
83+
glfw.PollEvents()
84+
if window.GetKey(glfw.KeyEscape) == glfw.Press {
85+
window.SetShouldClose(true)
86+
}
87+
}
88+
}
89+
90+
var vertexShader string = `
91+
#version 330
92+
in vec3 vert;
93+
94+
void main() {
95+
gl_Position = vec4(vert,1);
96+
}
97+
` + "\x00"
98+
99+
var fragmentShader string = `
100+
#version 330
101+
out vec4 outputColor;
102+
103+
void main() {
104+
outputColor = vec4(1.0,0.0,0.0,1.0);
105+
}
106+
` + "\x00"
107+
108+
var triangleVertices = []float32{
109+
-1.0, -1.0,
110+
1.0, -1.0,
111+
0.0, 1.0,
112+
}
113+
114+
func CompileProgram(vertexSrcCode, fragmentSrcCode string) (program uint32, err error) {
115+
program = gl.CreateProgram()
116+
vid, err := compile(gl.VERTEX_SHADER, vertexSrcCode)
117+
if err != nil {
118+
return 0, fmt.Errorf("vertex shader compile: %w", err)
119+
}
120+
fid, err := compile(gl.FRAGMENT_SHADER, fragmentSrcCode)
121+
if err != nil {
122+
return 0, fmt.Errorf("fragment shader compile: %w", err)
123+
}
124+
gl.AttachShader(program, vid)
125+
gl.AttachShader(program, fid)
126+
gl.LinkProgram(program)
127+
log := ivLog(program, gl.LINK_STATUS, gl.GetProgramiv, gl.GetProgramInfoLog)
128+
if len(log) > 0 {
129+
return 0, fmt.Errorf("link failed: %v", log)
130+
}
131+
// We should technically call DetachShader after linking... https://www.youtube.com/watch?v=71BLZwRGUJE&list=PLlrATfBNZ98foTJPJ_Ev03o2oq3-GGOS2&index=7&ab_channel=TheCherno
132+
gl.ValidateProgram(program)
133+
log = ivLog(program, gl.VALIDATE_STATUS, gl.GetProgramiv, gl.GetProgramInfoLog)
134+
if len(log) > 0 {
135+
return 0, fmt.Errorf("validation failed: %v", log)
136+
}
137+
138+
// We can clean up.
139+
gl.DeleteShader(vid)
140+
gl.DeleteShader(fid)
141+
return program, nil
142+
}
143+
144+
func compile(shaderType uint32, sourceCode string) (uint32, error) {
145+
id := gl.CreateShader(shaderType)
146+
csources, free := gl.Strs(sourceCode)
147+
gl.ShaderSource(id, 1, csources, nil)
148+
free()
149+
gl.CompileShader(id)
150+
151+
// We now check the errors during compile, if there were any.
152+
log := ivLog(id, gl.COMPILE_STATUS, gl.GetShaderiv, gl.GetShaderInfoLog)
153+
if len(log) > 0 {
154+
return 0, errors.New(log)
155+
}
156+
return id, nil
157+
}
158+
159+
// ivLog is a helper function for extracting log data
160+
// from a Shader compilation step or program linking.
161+
//
162+
// log := ivLog(id, gl.COMPILE_STATUS, gl.GetShaderiv, gl.GetShaderInfoLog)
163+
// if len(log) > 0 {
164+
// return 0, errors.New(log)
165+
// }
166+
func ivLog(id, plName uint32, getIV func(program uint32, pname uint32, params *int32), getInfo func(program uint32, bufSize int32, length *int32, infoLog *uint8)) string {
167+
var iv int32
168+
getIV(id, plName, &iv)
169+
if iv == gl.FALSE {
170+
var logLength int32
171+
getIV(id, gl.INFO_LOG_LENGTH, &logLength)
172+
log := make([]byte, logLength)
173+
getInfo(id, logLength, &logLength, &log[0])
174+
return string(log[:len(log)-1]) // we exclude the last null character.
175+
}
176+
return ""
177+
}

0 commit comments

Comments
 (0)