mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 13:28:20 +00:00
Support combined shaders+allow loading shaders from string
This commit is contained in:
10
main.go
10
main.go
@ -19,10 +19,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//TODO: Tasks:
|
//TODO: Tasks:
|
||||||
// Build simple game
|
|
||||||
// Integrate physx
|
|
||||||
// Entities and components
|
|
||||||
// Camera class
|
// Camera class
|
||||||
|
// Entities and components
|
||||||
|
// Integrate physx
|
||||||
|
|
||||||
//Low Priority:
|
//Low Priority:
|
||||||
// Create VAO struct independent from VBO to support multi-VBO use cases (e.g. instancing)
|
// Create VAO struct independent from VBO to support multi-VBO use cases (e.g. instancing)
|
||||||
@ -31,7 +30,6 @@ import (
|
|||||||
// Separate engine loop from rendering loop? or leave it to the user?
|
// Separate engine loop from rendering loop? or leave it to the user?
|
||||||
// Abstract keys enum away from sdl
|
// Abstract keys enum away from sdl
|
||||||
// Proper Asset loading
|
// Proper Asset loading
|
||||||
// Audio
|
|
||||||
// Frustum culling
|
// Frustum culling
|
||||||
// Material system editor with fields automatically extracted from the shader
|
// Material system editor with fields automatically extracted from the shader
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ type OurGame struct {
|
|||||||
func (g *OurGame) Init() {
|
func (g *OurGame) Init() {
|
||||||
|
|
||||||
//Create materials
|
//Create materials
|
||||||
simpleMat = materials.NewMaterial("Simple Mat", "./res/shaders/simple")
|
simpleMat = materials.NewMaterial("Simple Mat", "./res/shaders/simple.glsl")
|
||||||
|
|
||||||
//Load meshes
|
//Load meshes
|
||||||
var err error
|
var err error
|
||||||
@ -98,7 +96,7 @@ func (g *OurGame) Init() {
|
|||||||
|
|
||||||
func (g *OurGame) Update() {
|
func (g *OurGame) Update() {
|
||||||
|
|
||||||
if input.IsQuitClicked() {
|
if input.IsQuitClicked() || input.KeyClicked(sdl.K_ESCAPE) {
|
||||||
engine.Quit()
|
engine.Quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -106,24 +106,20 @@ func (m *Material) Delete() {
|
|||||||
|
|
||||||
func NewMaterial(matName, shaderPath string) *Material {
|
func NewMaterial(matName, shaderPath string) *Material {
|
||||||
|
|
||||||
shdrProg, err := shaders.NewShaderProgram()
|
shdrProg, err := shaders.LoadAndCompileCombinedShader(shaderPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.ErrLog.Fatalln("Failed to create new shader program. Err: ", err)
|
logging.ErrLog.Fatalln("Failed to create new material. Err: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Material{Name: matName, ShaderProg: shdrProg, UnifLocs: make(map[string]int32), AttribLocs: make(map[string]int32)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMaterialSrc(matName string, shaderSrc []byte) *Material {
|
||||||
|
|
||||||
|
shdrProg, err := shaders.LoadAndCompileCombinedShaderSrc(shaderSrc)
|
||||||
|
if err != nil {
|
||||||
|
logging.ErrLog.Fatalln("Failed to create new material. Err: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
vertShader, err := shaders.LoadAndCompilerShader(shaderPath+".vert.glsl", shaders.VertexShaderType)
|
|
||||||
if err != nil {
|
|
||||||
logging.ErrLog.Fatalln("Failed to load and create vertex shader. Err: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fragShader, err := shaders.LoadAndCompilerShader(shaderPath+".frag.glsl", shaders.FragmentShaderType)
|
|
||||||
if err != nil {
|
|
||||||
logging.ErrLog.Fatalln("Failed to load and create fragment shader. Err: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
shdrProg.AttachShader(vertShader)
|
|
||||||
shdrProg.AttachShader(fragShader)
|
|
||||||
shdrProg.Link()
|
|
||||||
|
|
||||||
return &Material{Name: matName, ShaderProg: shdrProg, UnifLocs: make(map[string]int32), AttribLocs: make(map[string]int32)}
|
return &Material{Name: matName, ShaderProg: shdrProg, UnifLocs: make(map[string]int32), AttribLocs: make(map[string]int32)}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
#version 410
|
|
||||||
|
|
||||||
uniform sampler2D Texture;
|
|
||||||
|
|
||||||
in vec2 Frag_UV;
|
|
||||||
in vec4 Frag_Color;
|
|
||||||
|
|
||||||
out vec4 Out_Color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
Out_Color = vec4(Frag_Color.rgb, Frag_Color.a * texture(Texture, Frag_UV.st).r);
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
#version 410
|
|
||||||
|
|
||||||
uniform mat4 ProjMtx;
|
|
||||||
|
|
||||||
in vec2 Position;
|
|
||||||
in vec2 UV;
|
|
||||||
in vec4 Color;
|
|
||||||
|
|
||||||
out vec2 Frag_UV;
|
|
||||||
out vec4 Frag_Color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
Frag_UV = UV;
|
|
||||||
Frag_Color = Color;
|
|
||||||
gl_Position = ProjMtx * vec4(Position.xy, 0, 1);
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
#version 410
|
|
||||||
|
|
||||||
uniform float ambientStrength = 0.1;
|
|
||||||
uniform vec3 ambientLightColor = vec3(1, 1, 1);
|
|
||||||
|
|
||||||
uniform vec3 lightPos1;
|
|
||||||
uniform vec3 lightColor1;
|
|
||||||
|
|
||||||
uniform sampler2D diffTex;
|
|
||||||
|
|
||||||
in vec3 vertColor;
|
|
||||||
in vec3 vertNormal;
|
|
||||||
in vec2 vertUV0;
|
|
||||||
in vec3 fragPos;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec3 lightDir = normalize(lightPos1 - fragPos);
|
|
||||||
float diffStrength = max(0.0, dot(normalize(vertNormal), lightDir));
|
|
||||||
|
|
||||||
vec3 finalAmbientColor = ambientLightColor * ambientStrength;
|
|
||||||
vec4 texColor = texture(diffTex, vertUV0);
|
|
||||||
fragColor = vec4(texColor.rgb * vertColor * (finalAmbientColor + diffStrength*lightColor1) , texColor.a);
|
|
||||||
}
|
|
||||||
55
res/shaders/simple.glsl
Executable file
55
res/shaders/simple.glsl
Executable file
@ -0,0 +1,55 @@
|
|||||||
|
//shader:vertex
|
||||||
|
#version 410
|
||||||
|
|
||||||
|
layout(location=0) in vec3 vertPosIn;
|
||||||
|
layout(location=1) in vec3 vertNormalIn;
|
||||||
|
layout(location=2) in vec2 vertUV0In;
|
||||||
|
layout(location=3) in vec3 vertColorIn;
|
||||||
|
|
||||||
|
out vec3 vertNormal;
|
||||||
|
out vec2 vertUV0;
|
||||||
|
out vec3 vertColor;
|
||||||
|
out vec3 fragPos;
|
||||||
|
|
||||||
|
//MVP = Model View Projection
|
||||||
|
uniform mat4 modelMat;
|
||||||
|
uniform mat4 viewMat;
|
||||||
|
uniform mat4 projMat;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vertNormal = mat3(transpose(inverse(modelMat))) * vertNormalIn;
|
||||||
|
vertUV0 = vertUV0In;
|
||||||
|
vertColor = vertColorIn;
|
||||||
|
fragPos = vec3(modelMat * vec4(vertPosIn, 1.0));
|
||||||
|
|
||||||
|
gl_Position = projMat * viewMat * modelMat * vec4(vertPosIn, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//shader:fragment
|
||||||
|
#version 410
|
||||||
|
|
||||||
|
uniform float ambientStrength = 0.1;
|
||||||
|
uniform vec3 ambientLightColor = vec3(1, 1, 1);
|
||||||
|
|
||||||
|
uniform vec3 lightPos1;
|
||||||
|
uniform vec3 lightColor1;
|
||||||
|
|
||||||
|
uniform sampler2D diffTex;
|
||||||
|
|
||||||
|
in vec3 vertColor;
|
||||||
|
in vec3 vertNormal;
|
||||||
|
in vec2 vertUV0;
|
||||||
|
in vec3 fragPos;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 lightDir = normalize(lightPos1 - fragPos);
|
||||||
|
float diffStrength = max(0.0, dot(normalize(vertNormal), lightDir));
|
||||||
|
|
||||||
|
vec3 finalAmbientColor = ambientLightColor * ambientStrength;
|
||||||
|
vec4 texColor = texture(diffTex, vertUV0);
|
||||||
|
fragColor = vec4(texColor.rgb * vertColor * (finalAmbientColor + diffStrength*lightColor1) , texColor.a);
|
||||||
|
}
|
||||||
@ -1,26 +0,0 @@
|
|||||||
#version 410
|
|
||||||
|
|
||||||
layout(location=0) in vec3 vertPosIn;
|
|
||||||
layout(location=1) in vec3 vertNormalIn;
|
|
||||||
layout(location=2) in vec2 vertUV0In;
|
|
||||||
layout(location=3) in vec3 vertColorIn;
|
|
||||||
|
|
||||||
out vec3 vertNormal;
|
|
||||||
out vec2 vertUV0;
|
|
||||||
out vec3 vertColor;
|
|
||||||
out vec3 fragPos;
|
|
||||||
|
|
||||||
//MVP = Model View Projection
|
|
||||||
uniform mat4 modelMat;
|
|
||||||
uniform mat4 viewMat;
|
|
||||||
uniform mat4 projMat;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vertNormal = mat3(transpose(inverse(modelMat))) * vertNormalIn;
|
|
||||||
vertUV0 = vertUV0In;
|
|
||||||
vertColor = vertColorIn;
|
|
||||||
fragPos = vec3(modelMat * vec4(vertPosIn, 1.0));
|
|
||||||
|
|
||||||
gl_Position = projMat * viewMat * modelMat * vec4(vertPosIn, 1.0);
|
|
||||||
}
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package shaders
|
package shaders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -28,14 +29,69 @@ func NewShaderProgram() (ShaderProgram, error) {
|
|||||||
return ShaderProgram{ID: id}, nil
|
return ShaderProgram{ID: id}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadAndCompilerShader(shaderPath string, shaderType ShaderType) (Shader, error) {
|
func LoadAndCompileCombinedShader(shaderPath string) (ShaderProgram, error) {
|
||||||
|
|
||||||
shaderSource, err := os.ReadFile(shaderPath)
|
combinedSource, err := os.ReadFile(shaderPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.ErrLog.Println("Failed to read shader. Err: ", err)
|
logging.ErrLog.Println("Failed to read shader. Err: ", err)
|
||||||
return Shader{}, err
|
return ShaderProgram{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return LoadAndCompileCombinedShaderSrc(combinedSource)
|
||||||
|
|
||||||
|
}
|
||||||
|
func LoadAndCompileCombinedShaderSrc(shaderSrc []byte) (ShaderProgram, error) {
|
||||||
|
|
||||||
|
shaderSources := bytes.Split(shaderSrc, []byte("//shader:"))
|
||||||
|
if len(shaderSources) == 1 {
|
||||||
|
return ShaderProgram{}, errors.New("failed to read combined shader. Did not find '//shader:vertex' or '//shader:fragment'")
|
||||||
|
}
|
||||||
|
|
||||||
|
shdrProg, err := NewShaderProgram()
|
||||||
|
if err != nil {
|
||||||
|
return ShaderProgram{}, errors.New("failed to create new shader program. Err: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedShdrCount := 0
|
||||||
|
for i := 0; i < len(shaderSources); i++ {
|
||||||
|
|
||||||
|
src := shaderSources[i]
|
||||||
|
|
||||||
|
//This can happen when the shader type is at the start of the file
|
||||||
|
if len(bytes.TrimSpace(src)) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var shdrType ShaderType
|
||||||
|
if bytes.HasPrefix(src, []byte("vertex")) {
|
||||||
|
src = src[6:]
|
||||||
|
shdrType = VertexShaderType
|
||||||
|
} else if bytes.HasPrefix(src, []byte("fragment")) {
|
||||||
|
src = src[8:]
|
||||||
|
shdrType = FragmentShaderType
|
||||||
|
} else {
|
||||||
|
return ShaderProgram{}, errors.New("unknown shader type. Must be '//shader:vertex' or '//shader:fragment'")
|
||||||
|
}
|
||||||
|
|
||||||
|
shdr, err := CompileShaderOfType(src, shdrType)
|
||||||
|
if err != nil {
|
||||||
|
return ShaderProgram{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedShdrCount++
|
||||||
|
shdrProg.AttachShader(shdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if loadedShdrCount == 0 {
|
||||||
|
return ShaderProgram{}, errors.New("no valid shaders found. Please put '//shader:vertex' or '//shader:fragment' before your shaders")
|
||||||
|
}
|
||||||
|
|
||||||
|
shdrProg.Link()
|
||||||
|
return shdrProg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CompileShaderOfType(shaderSource []byte, shaderType ShaderType) (Shader, error) {
|
||||||
|
|
||||||
shaderID := gl.CreateShader(uint32(shaderType))
|
shaderID := gl.CreateShader(uint32(shaderType))
|
||||||
if shaderID == 0 {
|
if shaderID == 0 {
|
||||||
logging.ErrLog.Println("Failed to create shader.")
|
logging.ErrLog.Println("Failed to create shader.")
|
||||||
|
|||||||
@ -149,11 +149,47 @@ func (i *ImguiInfo) AddFontTTF(fontPath string, fontSize float32, fontConfig *im
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const imguiShdrSrc = `
|
||||||
|
//shader:vertex
|
||||||
|
#version 410
|
||||||
|
|
||||||
|
uniform mat4 ProjMtx;
|
||||||
|
|
||||||
|
in vec2 Position;
|
||||||
|
in vec2 UV;
|
||||||
|
in vec4 Color;
|
||||||
|
|
||||||
|
out vec2 Frag_UV;
|
||||||
|
out vec4 Frag_Color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Frag_UV = UV;
|
||||||
|
Frag_Color = Color;
|
||||||
|
gl_Position = ProjMtx * vec4(Position.xy, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//shader:fragment
|
||||||
|
#version 410
|
||||||
|
|
||||||
|
uniform sampler2D Texture;
|
||||||
|
|
||||||
|
in vec2 Frag_UV;
|
||||||
|
in vec4 Frag_Color;
|
||||||
|
|
||||||
|
out vec4 Out_Color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Out_Color = vec4(Frag_Color.rgb, Frag_Color.a * texture(Texture, Frag_UV.st).r);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
func NewImGUI() ImguiInfo {
|
func NewImGUI() ImguiInfo {
|
||||||
|
|
||||||
imguiInfo := ImguiInfo{
|
imguiInfo := ImguiInfo{
|
||||||
ImCtx: imgui.CreateContext(nil),
|
ImCtx: imgui.CreateContext(nil),
|
||||||
Mat: materials.NewMaterial("ImGUI Mat", "./res/shaders/imgui"),
|
Mat: materials.NewMaterialSrc("ImGUI Mat", []byte(imguiShdrSrc)),
|
||||||
}
|
}
|
||||||
|
|
||||||
imIO := imgui.CurrentIO()
|
imIO := imgui.CurrentIO()
|
||||||
|
|||||||
Reference in New Issue
Block a user