[Solved] How to make an interpolated Triangle w/ vertex & pixel shaders?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
-
- Prole
- Posts: 7
- Joined: Sun Jan 22, 2023 3:42 pm
[Solved] How to make an interpolated Triangle w/ vertex & pixel shaders?
I've been trying to make one of those interpolated triangles that has 3 main colors at the vertices of a triangle: Red, Green and Blue. However, I have absolutely no idea how to implement this in Love2D with GLSL. I'm trying to follow a tutorial that is focused on OpenGL and GLSL and all of those other libraries and they go from Vertex Shader to Fragment Shader and that somehow interpolates some color. However, since I can't use the "in" and "out" keywords, I really just don't know how to make this. The code also uses gl_VertexID which doesn't seem to work either. Next to that, when I try to make an int value, it asks for it to be a "flat in" if I put it under: "#ifdef PIXEL", but when I add it infront of my constructor I get "Unexpected Identifier" with "flat in int MyInteger;". Everything is just a mess and it's only getting worse! Help is very much appreciated. Since I'm new to using shaders and love2d I might have made a dumb mistake. I don't know if I'm allowed to link the tutorial so I didn't include the link. I believe there was another post with the same topic, but there was not a solution for it and maybe there is one now. I'm trying to make a 3D renderer btw. So I first transform my triangles using the vertex shader, but then I want to add those interpolated colors, just like the tutorial.
Last edited by AllanAxolotls on Sat Jan 28, 2023 8:55 am, edited 3 times in total.
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
Something that looks like this? (I slightly customized it to my taste). Say if it's good what you want to talk about when you say "interpolated triangles" and by the way why do you want to do it on Löve2d and not directly with OpenGL which seems more appropriate to me? (in the sense that you'll learn more by wanting to do it directly on OpenGL but that's just my opinion)
In any case this page could help you: https://love2d.org/wiki/Shader_Variables
And to pass values from a vertex shader to the fragment shader you can use `varying`.
Edit:
By reading your post a bit and doing some research I think I understood what you want, here is what I did, from what I understood from your post you must have the basics to understand how the code works but if you have any doubts do not hesitate to ask me:
I had never done it before but with these pages from the Löve2D documentation: love.graphics.newMesh and Shader Variables.
And also this page which made me understand what you wanted I managed to realize it, so I hope that with all this you will also understand and that you can redo it to your sauce
Code: Select all
local lg = love.graphics
-- Create the triangle vertices
local vertices = {
{-0.5, -0.5, 1, 0, 0},
{0.5, -0.5, 0, 1, 0},
{0, 0.5, 0, 0, 1}
}
-- Create a new mesh to hold the triangle
local triangle = lg.newMesh(vertices, "triangles")
-- Create the color interpolation shader
local shader = lg.newShader[[
extern number time;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
return vec4(texture_coords, sin(time), 1.0);
}
]]
function love.draw()
shader:send("time", love.timer.getTime())
lg.setShader(shader)
lg.draw(triangle,lg.getWidth()/2,lg.getHeight()/2,0,100,100)
lg.setShader()
end
And to pass values from a vertex shader to the fragment shader you can use `varying`.
Edit:
By reading your post a bit and doing some research I think I understood what you want, here is what I did, from what I understood from your post you must have the basics to understand how the code works but if you have any doubts do not hesitate to ask me:
Code: Select all
local lg = love.graphics
-- Create attributes of the triangle
local attributes = {
{"VertexPosition", "float", 2},
{"VertexColor", "byte", 4},
}
-- Create the triangle vertices
local vertices = {
{-0.5, -0.5, 1, 0, 0},
{0.5, -0.5, 0, 1, 0},
{0, 0.5, 0, 0, 1}
}
-- Create a new mesh to hold the triangle
local triangle = lg.newMesh(attributes, vertices, "triangles", "static")
-- Set up the color interpolation shader
local shader = lg.newShader([[
varying vec4 vColor;
vec4 position( mat4 transform_projection, vec4 vertex_position ) {
vColor = VertexColor;
return transform_projection * vertex_position;
}
]], [[
varying vec4 vColor;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
return vColor;
}
]])
function love.draw()
lg.setShader(shader)
lg.draw(triangle,lg.getWidth()/2,lg.getHeight()/2,0,200,200)
lg.setShader()
end
And also this page which made me understand what you wanted I managed to realize it, so I hope that with all this you will also understand and that you can redo it to your sauce
- Attachments
-
- Triangle-interpolation.love
- (578 Bytes) Downloaded 89 times
Last edited by Bigfoot71 on Sun Jan 22, 2023 11:07 pm, edited 2 times in total.
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
I think you can just use the "varying" qualifier to describe an interpolated out in the vertex shader, as seen in this macro here in the Löve source:
https://github.com/love2d/love/blob/mai ... r.lua#L202
Edit: hm, and using "varying" again for the in attribute in the fragment shader, as seen a few lines below with another macro:
https://github.com/love2d/love/blob/mai ... r.lua#L248
https://github.com/love2d/love/blob/mai ... r.lua#L202
Edit: hm, and using "varying" again for the in attribute in the fragment shader, as seen a few lines below with another macro:
https://github.com/love2d/love/blob/mai ... r.lua#L248
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
Exactly, after I must admit that launching nothing with only OpenGL tutorials and this information on "varying" and no other basis, I'm not sure that we can achieve it. Personally I think I could have given up if I put myself in his place. Quite special anyway what you have set yourself as a goal with Löve2D I think, but the biggest ones start like thisRNavega wrote: ↑Sun Jan 22, 2023 10:35 pm I think you can just use the "varying" qualifier to describe an interpolated out in the vertex shader, as seen in this macro here in the Löve source:
https://github.com/love2d/love/blob/mai ... r.lua#L202
Edit: hm, and using "varying" again for the in attribute in the fragment shader, as seen a few lines below with another macro:
https://github.com/love2d/love/blob/mai ... r.lua#L248
(then maybe there is a simpler method than mine and that I am getting the wrong ideas?)
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
@Bigfoot71 hi. I'm not sure if I understand what you mean, but your added code at the end, with "varying vec4 vColor", looks exactly what needs to be done: a value calculated in the vertex shader stage passed around to the fragment stage using "varying", which is a legacy keyword that when used in shader code with Löve will be shadowed by Löve's #DEFINE macros.
Using that, if the GLSL version in the device running Löve is below 1.30, it'll stay as the legacy "varying" qualifier, and if it's above, it'll be overriden to be "out" in the vertex shader and "in" in the pixel shader, with no interpolation qualifiers at all, defaulting to "smooth" interpolation, as per the OpenGL wiki.
Cheers
Using that, if the GLSL version in the device running Löve is below 1.30, it'll stay as the legacy "varying" qualifier, and if it's above, it'll be overriden to be "out" in the vertex shader and "in" in the pixel shader, with no interpolation qualifiers at all, defaulting to "smooth" interpolation, as per the OpenGL wiki.
Cheers
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
Note that I added the vertex shader as an example to show how to pass a variable from the vertex to the fragment, but the variable `VertexColor` to a correspondence directly offered by Löve accessible in the fragment shader which is `VaryingColor` so the last shader that I proposed can be simplified like this:
Hence the fact that I say that doing it directly in OpenGL allows you to learn more because Löve does a lot of work for us at this level. After once this kind of basic acquired Löve still allows you to progress faster on learning because this kind of tests are faster to perform in Lua but you must already have these basics. Hence once again the fact that I wonder about the usefulness of following an OpenGL tutorial with Löve2d, after again it's only my opinion, I may be wrong.
Edit: I'm thinking about it but if you really want to do all that in Löve2d I can only recommend this blog post on shaders in Löve2d which is very useful! https://blogs.love2d.org/content/beginn ... de-shaders
Code: Select all
local shader = lg.newShader([[
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
return VaryingColor;
}
]])
Edit: I'm thinking about it but if you really want to do all that in Löve2d I can only recommend this blog post on shaders in Löve2d which is very useful! https://blogs.love2d.org/content/beginn ... de-shaders
-
- Prole
- Posts: 7
- Joined: Sun Jan 22, 2023 3:42 pm
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
It works! When I used love.graphics.newShader, the first argument I used was the fragment shader instead of the vertex shader, could that have caused issues? It looked like this:Bigfoot71 wrote: ↑Sun Jan 22, 2023 10:11 pm Something that looks like this? (I slightly customized it to my taste). Say if it's good what you want to talk about when you say "interpolated triangles" and by the way why do you want to do it on Löve2d and not directly with OpenGL which seems more appropriate to me? (in the sense that you'll learn more by wanting to do it directly on OpenGL but that's just my opinion)
In any case this page could help you: https://love2d.org/wiki/Shader_VariablesCode: Select all
local lg = love.graphics -- Create the triangle vertices local vertices = { {-0.5, -0.5, 1, 0, 0}, {0.5, -0.5, 0, 1, 0}, {0, 0.5, 0, 0, 1} } -- Create a new mesh to hold the triangle local triangle = lg.newMesh(vertices, "triangles") -- Create the color interpolation shader local shader = lg.newShader[[ extern number time; vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { return vec4(texture_coords, sin(time), 1.0); } ]] function love.draw() shader:send("time", love.timer.getTime()) lg.setShader(shader) lg.draw(triangle,lg.getWidth()/2,lg.getHeight()/2,0,100,100) lg.setShader() end
And to pass values from a vertex shader to the fragment shader you can use `varying`.
Edit:
By reading your post a bit and doing some research I think I understood what you want, here is what I did, from what I understood from your post you must have the basics to understand how the code works but if you have any doubts do not hesitate to ask me:
I had never done it before but with these pages from the Löve2D documentation: love.graphics.newMesh and Shader Variables.Code: Select all
local lg = love.graphics -- Create attributes of the triangle local attributes = { {"VertexPosition", "float", 2}, {"VertexColor", "byte", 4}, } -- Create the triangle vertices local vertices = { {-0.5, -0.5, 1, 0, 0}, {0.5, -0.5, 0, 1, 0}, {0, 0.5, 0, 0, 1} } -- Create a new mesh to hold the triangle local triangle = lg.newMesh(attributes, vertices, "triangles", "static") -- Set up the color interpolation shader local shader = lg.newShader([[ varying vec4 vColor; vec4 position( mat4 transform_projection, vec4 vertex_position ) { vColor = VertexColor; return transform_projection * vertex_position; } ]], [[ varying vec4 vColor; vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) { return vColor; } ]]) function love.draw() lg.setShader(shader) lg.draw(triangle,lg.getWidth()/2,lg.getHeight()/2,0,200,200) lg.setShader() end
And also this page which made me understand what you wanted I managed to realize it, so I hope that with all this you will also understand and that you can redo it to your sauce
Code: Select all
shader = love.graphics.newShader(FragmentCode, VertexCode)
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
The order for arguments between vertex and fragment shader doesn't matter, love2d detects the `effect` and `position` functions itself, you can even combine them into one in the `newShader` parameter like this (as it says in the doc for love.graphics.newShader):
Finally `VertexColor` precisely represents the color of a vertex in shaders, it is generally used to give a specific color to each vertex of a polygon, rather than using a single color for the whole polygon, in "real" use this can help create color transition effects on the edges of polygons, among other things. Or rather as it is written in the page Shader variables of the doc: "The color of the vertex, sprite, or text character if a Mesh, SpriteBatch, or Text object with per-vertex colors is drawn"
For more details and to answer your question, YES, from what I know the VertexColor variable, which is defined in the vertex shader, is assigned a value for each vertex in the geometry, then when those vertices are connected to form triangles, the rasterizer uses a barycentric interpolation algorithm to interpolate the VertexColor values between the vertices. This means that for each pixel in a triangle, the rasterizer determines an interpolated value of vColor based on the position of the pixel relative to the vertices of the triangle. These interpolated values are then used by the fragment shader to determine the final color of the pixel.
In summary the barycentric interpolation algorithm is used to interpolate the values of the triangle according to their position relative to the vertices of the triangle but it is also used to calculate the values of variables such as normals, texture coordinates, etc for each pixel in the triangle. If you're interested in math, there's this Wikipedia article that looks pretty good: https://en.wikipedia.org/wiki/Interpolation
If you want to say that the problem is solved you can edit the title of your question and add a small [Solved] for example
(If I ever made any inaccuracies or errors please correct me, I also encourage you to do your own research )
Code: Select all
lg.newShader[[
varying vec4 vpos;
#ifdef VERTEX
vec4 position( mat4 transform_projection, vec4 vertex_position )
{
vpos = vertex_position;
return transform_projection * vertex_position;
}
#endif
#ifdef PIXEL
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
texture_coords += vec2(cos(vpos.x), sin(vpos.y));
vec4 texcolor = Texel(tex, texture_coords);
return texcolor * color;
}
#endif
]]
For more details and to answer your question, YES, from what I know the VertexColor variable, which is defined in the vertex shader, is assigned a value for each vertex in the geometry, then when those vertices are connected to form triangles, the rasterizer uses a barycentric interpolation algorithm to interpolate the VertexColor values between the vertices. This means that for each pixel in a triangle, the rasterizer determines an interpolated value of vColor based on the position of the pixel relative to the vertices of the triangle. These interpolated values are then used by the fragment shader to determine the final color of the pixel.
In summary the barycentric interpolation algorithm is used to interpolate the values of the triangle according to their position relative to the vertices of the triangle but it is also used to calculate the values of variables such as normals, texture coordinates, etc for each pixel in the triangle. If you're interested in math, there's this Wikipedia article that looks pretty good: https://en.wikipedia.org/wiki/Interpolation
If you want to say that the problem is solved you can edit the title of your question and add a small [Solved] for example
(If I ever made any inaccuracies or errors please correct me, I also encourage you to do your own research )
-
- Prole
- Posts: 7
- Joined: Sun Jan 22, 2023 3:42 pm
Re: How to make an interpolated Triangle w/ vertex & pixel shaders?
That's nice! Now I just need to find a way to also include the Z-axis in the vertices when I create the new triangle mesh. Somewhere on the docs of love2d it was stated that using .newMesh a lot per frame can cause performance issues. So I want to just make a main array that holds every triangle mesh in the "World". However, when using .newMesh, doesn't the z data of all the vertices get lost? When I scrolled through the docs of love.graphics.newMesh I couldn't find any argument for a z-axis. This way the data wouldn't transfer to the VertexShader. Is there any solution for this?
Re: [Solved] How to make an interpolated Triangle w/ vertex & pixel shaders?
Well here you are getting into something big with Löve2D but to add the Z axis in the meshes it seems to me that you only have to modify the `VertexPosition` value in the attributes like this:
I changed `{"VertexPosition", "float", 2}` to ` {"VertexPosition", "float", 3}`. Otherwise yes the use of a lot of meshes has an impact on performance but like everything I want to say, it's just a warning to say "use only what is necessary", if I understand correctly your question.
Otherwise, unless you want to completely recreate a 3D engine with Löve2D (I don't really understand what you want to do) you can use the g3d library which is just awesome and very easy to use
Code: Select all
local attributes = {
{"VertexPosition", "float", 3},
{"VertexColor", "byte", 4},
}
Otherwise, unless you want to completely recreate a 3D engine with Löve2D (I don't really understand what you want to do) you can use the g3d library which is just awesome and very easy to use
Last edited by Bigfoot71 on Mon Jan 23, 2023 4:02 pm, edited 1 time in total.
Who is online
Users browsing this forum: Ahrefs [Bot], Google [Bot] and 4 guests