I'm rendering a tree using spheres and cylinders, and i use normal mapping to map bark texture
on the sphere and cylinder. Below is my vertex shader:
// Normal mapping light shader
// Vertex Shader
#version 130
// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;
in vec4 vTexture0;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
// Color to fragment program
vec3 vEyeNormal;
smooth out vec3 vVaryingLightDir;
smooth out vec2 vTexCoords;
vec3 vTangent = vec3(1.0, 0.0, 0.0);
void main(void)
{
// Tangent Basis
vec3 b, t, v;
// Get surface normal in eye coordinates
vEyeNormal = normalMatrix * vNormal;
// Get vertex position in eye coordinates
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Get vector to light source
vVaryingLightDir = normalize(vLightPosition - vPosition3);
// Build Tangent Basis
t = normalize(normalMatrix * vTangent);
b = cross(vEyeNormal, t);
v.x = dot(vVaryingLightDir, t);
v.y = dot(vVaryingLightDir, b);
v.z = dot(vVaryingLightDir, vEyeNormal);
vVaryingLightDir = normalize(v);
// Pass along the texture coordinates
vTexCoords = vTexture0.st;
// Don't forget to transform the geometry!
gl_Position = mvpMatrix * vVertex;
}
And this is the fragment shader:
// Normal mapping light shader
// Fragment Shader
#version 130
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
smooth in vec3 vVaryingLightDir;
smooth in vec2 vTexCoords;
out vec4 vFragColor;
void main(void)
{
vec3 vTextureNormal = texture2D(normalMap, vTexCoords).xyz;
vTextureNormal = (vTextureNormal - 0.5) * 2.0;
// Dot product gives us diffuse intensity
float diff = max(0.0, dot(normalize(vTextureNormal), normalize(vVaryingLightDir)));
// Multiply intensity by diffuse color, force alpha to 1.0
vFragColor = diff * diffuseColor;
// Add in ambient light
vFragColor += ambientColor;
vFragColor.rgb = min(vec3(1.0,1.0,1.0), vFragColor.rgb);
// Modulate in the texture
vFragColor *= texture(colorMap, vTexCoords);
}
But what i get is an ugly effect:
Can anybody tell me how i can make the bump mapping smooth?
Related
Currently I am rendering mesh triangles like this:
// draw the same polygons again
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
shader.setVec3("objectColor", obj_color);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(indices.size()), GL_UNSIGNED_INT, 0);
The problem with this code is that I am setting object color inside shader for the full mesh.
What would be a good way to render one single mesh whose faces have different colors?
For now I only know how to set vertex colors, and pass it the fragment shader.
What are the most common ways to set individual face colors?
I only think about duplicating mesh vertices twice to avoid vertex color interpolation.
My current shader looks like this:
Vertex Shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 FragPos;
out vec3 Normal;
out vec3 LightPos;
uniform vec3 lightPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
FragPos = vec3(view * model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(view * model))) * aNormal;
LightPos = vec3(vec4(lightPos, 1.0)); // Transform world-space light position to view-space light position
// FragPos = vec3(model * vec4(aPos, 1.0));
//Normal = mat3(transpose(inverse(model))) * aNormal;
// gl_Position = projection * view * vec4(FragPos, 1.0);
}
Fragment Shader:
#version 330 core
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec3 LightPos;
// extra in variable, since we need the light position in view space we calculate this in the vertex shader
uniform vec3 lightColor;
uniform vec3 objectColor;
uniform float f;
uniform float transparency;
void main()
{
//flat shading
// vec3 x_ = dFdx(FragPos);
// vec3 y_= dFdy(FragPos);
// vec3 normal_ = cross(x_, y_);
// vec3 norm_ = normalize(normal_);
// ambient
float ambientStrength = 0.75;
vec3 ambient = ambientStrength * lightColor;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(LightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);//change "norm_" to "norm" avoid the performance warning and have unwelded view
vec3 diffuse = diff * lightColor;
// specular
float specularStrength = 0.01;
vec3 viewDir = normalize(-FragPos); // the viewer is always at (0,0,0) in view-space, so viewDir is (0,0,0) - Position => -Position
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
vec3 shading = (ambient + diffuse + specular)*objectColor;
//float f = 0.75;
float r_interpolated = shading[0] + f * (objectColor[0] - shading[0]);
float g_interpolated = shading[1] + f * (objectColor[1] - shading[1]);
float b_interpolated = shading[2] + f * (objectColor[2] - shading[2]);
vec3 result = vec3(r_interpolated,g_interpolated,b_interpolated);
FragColor = vec4(result, transparency);
}
You can use the flat Interpolation qualifier:
The value will not be interpolated. The value given to the fragment shader is the value from the Provoking Vertex for that primitive.
Vertex shader
// [...]
layout (location = 0) in vec3 aColor;
flat out vec3 vColor;
void main()
{
vColor = aColor;
// [...]
}
Fragment shader
// [...]
flat in vec3 vColor;
void main()
{
FragColor = vec4(vColor, 1.0);
}
With this implementation, the entire triangle primitive is rendered with one color. If you find an intelligent system for assigning the color attributes to the vertices, you can render all triangles with different colors. e.g. 2 tringles with the indices 0-1-2 and 1-2-3. The color attribute of vertex 0 defines the color of the first triangle and the color attribute of vertex 1 defines the color of the 2nd triangle.
An alternative way would be to create an array of colors for each triangle primitive and store this color array in a Shader Storage Buffer Object. Use gl_VertexID to address the color in the vertex shader.
layout(std430, binding = 0) buffer primitiveColors
{
vec4 colors[];
};
void main()
{
vColor = colors[gl_VertexID / 3];
// [...]
}
I'm trying to implement normal mapping to my shaders but I keep getting weird results.
I already implemented diffuse and specular light (which are working).
I first calculated the normalized vector from the normal map : Ni = 2 * normalColor - 1
then calculated the binormal vector thanks to the cross vector of normal and tangent.
Finally I created the TBN matrix by transposing (tangent, binormal, normal)
Here is my code and some screenshots.
Vertex shader
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
in vec4 vertexTangent;
// Input uniform values
uniform mat4 mvp;
// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragPosition;
out vec4 fragTangent;
out vec3 fragNormal;
// out vec3 fragBiTangent;
// NOTE: Add here your custom variables
void main()
{
// Send vertex attributes to fragment shader
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
//added
fragNormal = vertexNormal;
fragPosition = vertexPosition;
fragTangent = vertexTangent;
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}
Fragment Shader
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragNormal;
in vec3 fragPosition;
in vec4 fragTangent;
// Input uniform values
uniform sampler2D texture0; // diffuse texture
uniform vec4 colDiffuse;
uniform vec3 lightPos; // light position
uniform mat4 matModel; // pos, rotation and scaling of object
uniform vec3 viewPos; // eyes position
uniform sampler2D normalMap; // normal texture
// Output fragment color
out vec4 finalColor;
// NOTE: Add here your custom variables
vec3 unHomogenous(vec4 v)
{
return v.xyz/v.w;
}
void main()
{
//=====================LOAD TEXTURES=============================
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord);
// obtain normal from normal map in range [0,1]
vec3 normalColor = texture(normalMap, fragTexCoord).xyz;
//=======================PARAMETERS==============================
// calculate normal in world coordinates
mat3 matNormal = transpose(inverse(mat3(matModel))); //CPU heavy
vec3 worldNormal = normalize(matNormal * fragNormal);
// Calculate the location of this fragment (pixel) in world coordinates
vec3 worldPosition = unHomogenous(matModel * vec4(fragPosition, 1.0));
//=======================NORMAL MAPPING========================
// transform normal vector to range [-1,1]
vec3 normal = normalize(normalColor * 2.0 - 1.0);
normal = normalize(matNormal * normal);
vec3 tangent = normalize(matNormal * fragTangent.xyz);
vec3 binormal = normalize(cross(normal, tangent));
mat3 TBN = mat3(tangent, binormal, worldNormal);
TBN = transpose(TBN);
//=======================DIFFUSING LIGHT===========================
// Shading is calculated by diffuse = (LightVect dot NormalVect) * Diffused color
vec3 ambiant = 0.01 * texelColor.xyz ;
// find light source : L = Lightposition - surfacePosition
vec3 lightDir = normalize(lightPos - worldPosition);
lightDir *= TBN; // NOT WORKING
// diffuse the light with the dot matrix :
float shading = clamp(dot(worldNormal, lightDir), 0.1, 1.0);
vec3 diffuse = shading * texelColor.xyz;
//=======================SPECULAR LIGHTNING====================
//intensity between 0 and 1
float specularStrength = 1;
// //calculate the view direction vector and corresponding reflect vector along the normal axis
vec3 viewDir = normalize(viewPos - worldPosition);
viewDir *= TBN; // NOT WORKING
vec3 reflectDir = reflect(-lightDir, worldNormal);
//Note that we negate the lightDir vector.
//The reflect function expects the first vector to point from the light source towards the fragment's position,
//but the lightDir vector is currently pointing the other way
// calclulate the specula component 32 is the shininess value of the highlight
int shininess = 32;
float spec = pow(clamp(dot(viewDir, reflectDir), 0.1, 1.0), shininess);
vec3 lightColor = vec3(1.0,1.0,1.0);
vec3 specular = specularStrength * spec * texelColor.xyz;
//=======================RENDER================================
finalColor = vec4(ambiant + diffuse + specular, 1.0);
}
main.cpp
#include "raylib.h"
#include "rlgl.h"
#include <math.h>
#include <raymath.h>
int main(void)
{
// Initialization
//[...]
//=====================WALL=======================//
Vector3 position = { -2.5f, 3.0f, 0.0f };
Model model = LoadModel("assets/models/wall.obj");
Texture2D texture = LoadTexture("assets/textures/cgaxis_pbr_17_stone_wall_5_diffuse.png");
// Set normal mapping
Texture2D normal_texture = LoadTexture("assets/textures/cgaxis_pbr_17_stone_wall_5_normal.png");
model.materials[0].maps[MATERIAL_MAP_NORMAL].texture = normal_texture;
//==========Generate mesh and diffuse texture=========//
GenMeshTangents(model.meshes);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
//===================SELECT SHADERS====================//
// Shader shader = LoadShader("assets/shaders/base.vs", "assets/shaders/base.fs"); // diffuse light
// Shader shader = LoadShader("assets/shaders/specular.vs", "assets/shaders/specular.fs"); // diff + specular
Shader shader = LoadShader("assets/shaders/normal_mapping.vs", "assets/shaders/normal_mapping.fs"); // diff + spec + normal mapping
// Set shader effect to 3d model
model.materials[0].shader = shader;
//==================Light======================//
Vector3 sunPos = {0.0f, 2.0f, 0.0f };
float rotation = 90.0f;
float radius = 5.0f;
// Diffuse light
int lightPosLoc = GetShaderLocation(shader, "lightPos");
float lightPos[] = {sunPos.x, sunPos.y, sunPos.z};
SetShaderValue(shader, lightPosLoc, lightPos, SHADER_UNIFORM_VEC3);
//specular light
int specularPosLoc = GetShaderLocation(shader, "viewPos");
float specularPos[] = {camera.position.x, camera.position.y, camera.position.z};
SetShaderValue(shader, specularPosLoc, specularPos, SHADER_UNIFORM_VEC3);
//RUN & draw
//[...]
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
diffuse + specular
normal mapping
sorry, I am a new on opengl es and processing
below processing and shaders output only background
PShader Gouraud,Phong;
rocket = loadShape("rocket.obj");
rocket.setFill(color(800, 0, 0));
Gouraud= loadShader("gouraudfragment.glsl","gouraudvertex.glsl");
Phong= loadShader("phongfragment.glsl","phongvertex.glsl");
background(0);
pushMatrix();
shader(Gouraud);
translate(130,height/2.0);
rotateY(rc);
rotateX(0.4);
noStroke();
fill(#800080);
box(100);
rc+=(0.02+speedCube);
rc*=dirCube;
popMatrix();
pushMatrix();
shader(Gouraud);
translate(width/2, height/2 + 100, -200);
rotateZ(PI);
rotateY(rr);
shape(rocket,100,100);
rr +=( 0.02+speedRocket);
rr*=dirRocket;
popMatrix();
vertex shader
varying vec3 N;
varying vec3 v;
varying vec4 diffuse;
varying vec4 spec;
attribute vec4 position;
attribute vec3 normal;
uniform mat4 modelview;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform vec4 lightPosition;
uniform vec3 lightAmbient;
uniform vec3 lightDiffuse;
uniform vec3 lightSpecular;
uniform float SpecularPower;
void main()
{
vec4 diffuse;
vec4 spec;
vec4 ambient;
v = vec3(modelview * position);
N = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * position;
vec3 L = normalize(lightPosition.xyz - v);
vec3 E = normalize(-v);
vec3 R = normalize(reflect(-L,N));
ambient = vec4(lightAmbient,100.0);
diffuse = vec4(clamp( lightDiffuse * max(dot(N,L), 0.0) , 0.0, 1.0 ) ,100.0);
spec = vec4(clamp (lightSpecular * pow(max(dot(R,E),0.0),0.3*SpecularPower) , 0.0, 1.0 ),100.0);
color = ambient + diffuse + spec;
}
fragment shader
void main()
{
gl_FragColor = color;
}
please help!
before apply gouraud shading
after apply gouraud shading
The prcessing load the obj and the draw a cube and apply a gouraud shader, but after that only backgroud are shown, the obj loaded and cube is gone. nothing shown!
the shader doesn't even compile and link. The vertex shader has 1 varying output (color), so the framgent shader needs the input varying vec4 color;.
varying vec4 color;
When you set the clip space position, then the vertex coordinate has to be transformed by the model view and projection matrix:
gl_Position = projectionMatrix * modelview * position;
The types specifications of v and N are missing and the types of ambient, diffuse and spec are vec4 rather than vec3.
Vertex shader:
attribute vec4 position;
attribute vec3 normal;
varying vec4 color;
uniform mat4 modelview;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform vec4 lightPosition;
uniform vec3 lightAmbient;
uniform vec3 lightDiffuse;
uniform vec3 lightSpecular;
uniform float SpecularPower;
void main()
{
vec3 v = vec3(modelview * position);
vec3 N = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelview * position;
vec3 L = normalize(lightPosition.xyz - v);
vec3 E = normalize(-v);
vec3 R = normalize(reflect(-L,N));
vec4 ambient = vec4(lightAmbient,100.0);
vec4 diffuse = vec4(clamp( lightDiffuse * max(dot(N,L), 0.0) , 0.0, 1.0 ) ,100.0);
vec4 spec = vec4(clamp (lightSpecular * pow(max(dot(R,E),0.0),0.3*SpecularPower) , 0.0, 1.0 ),100.0);
color = ambient + diffuse + spec;
}
Fragment shader:
varying vec4 color;
void main()
{
gl_FragColor = color;
}
Of course you have to set at least an ambient light source ambientLight().
You can use a directionalLight(), pointLight() or spotLight(), too.
But note, your shader can handle 1 light source only. More the 1 light source would gain
OpenGL error 1282 at top endDraw(): invalid operation
If you want to use more than 1 light source then you would have to use uniform arrays int the vertex shader for lightPosition, lightAmbient, lightDiffuse, and lightSpecular. See Types of shaders in Processing(https://processing.org/tutorials/pshader/)
Let's say the concept is to create a map consisting of cubes with a neon aesthetic, such as:
Currently I have this vertex shader:
// Uniforms
uniform mat4 u_projection;
uniform mat4 u_view;
uniform mat4 u_model;
// Vertex atributes
in vec3 a_position;
in vec3 a_normal;
in vec2 a_texture;
vec3 u_light_direction = vec3(1.0, 2.0, 3.0);
// Vertex shader outputs
out vec2 v_texture;
out float v_intensity;
void main()
{
vec3 normal = normalize((u_model * vec4(a_normal, 0.0)).xyz);
vec3 light_dir = normalize(u_light_direction);
v_intensity = max(0.0, dot(normal, light_dir));
v_texture = a_texture;
gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
}
And this pixel shader:
in float v_intensity;
in vec2 v_texture;
uniform sampler2D u_texture;
out vec4 fragColor;
void main()
{
fragColor = texture(u_texture, v_texture) * vec4(v_intensity, v_intensity, v_intensity, 1.0);
}
How would I use this to create a neon effect such as in the example for 3D cubes? The cubes are simply models with a mesh/material. The only change would be to set the material color to black and the outlines to a bright pink or blue (maybe with a glow).
Any help is appreciated. :)
You'd normally implement this as a post-processing effect. First render with bright, saturated colours into a texture, then apply a bloom effect, when drawing that texture to screen.
In the past few days I been trying to implement parallax mapping in my engine, but it doesn't seem to work, I have seen at least 15 examples, and I'm still not being able to get it to work
Here is an Image:
As you can see, all you can see is the base color, the height map is not there
Here are my shaders:
Fragment Shader
#version 330 core
uniform sampler2D DiffuseTextureSampler;
uniform sampler2D HeightTextureSampler;
vec2 scaleBias = vec2(0.5,0.5);
in vec3 EyeDirection_tangentspace;
in vec2 UV;
void main()
{
float height = texture2D(HeightTextureSampler, vec2 (UV.x, -UV.y)).r;
//Our heightmap only has one color channel.
float v = height * scaleBias.r - scaleBias.g;
vec3 eye = EyeDirection_tangentspace;
vec2 newCoords = UV + (eye.xy * v);
vec3 rgb = texture2D(DiffuseTextureSampler, vec2 (newCoords.x, -newCoords.y)).rgb;
gl_FragColor = vec4(rgb, 1.0);
}
Vertex Shader
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal_modelspace;
layout(location = 3) in vec3 vertexTangent_modelspace;
layout(location = 4) in vec3 vertexBitangent_modelspace;
// Output data ; will be interpolated for each fragment.
out vec2 UV;
out vec3 Position_worldspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;
out vec3 LightDirection_tangentspace;
out vec3 EyeDirection_tangentspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform mat3 MV3x3;
uniform vec3 LightPosition_worldspace;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
Position_worldspace = (M * vec4(vertexPosition_modelspace,1)).xyz;
// Vector that goes from the vertex to the camera, in camera space.
// In camera space, the camera is at the origin (0,0,0).
vec3 vertexPosition_cameraspace = ( V * M * vec4(vertexPosition_modelspace,1)).xyz;
EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;
UV = vertexUV;
vec3 vertexTangent_cameraspace = MV3x3 * vertexTangent_modelspace;
vec3 vertexBitangent_cameraspace = MV3x3 * vertexBitangent_modelspace;
vec3 vertexNormal_cameraspace = MV3x3 * vertexNormal_modelspace;
mat3 TBNMatrix = transpose(mat3(vertexTangent_cameraspace, vertexBitangent_cameraspace, vertexNormal_cameraspace));
EyeDirection_tangentspace = Position_worldspace - vertexPosition_modelspace.xyz;
EyeDirection_tangentspace *= TBNMatrix;
}
couple things
set your scale to 1. no point in halving your hightscale if you cant see it at all.
(YOUR CURRENT PROBLEM) you are getting your texture coordinates with -UV.y Opengl does not have negative texture coordinates. getting negative will pull nothing from the texture, or worse a mirrored textured if you have tiling on.
(YOUR NEXT PROBLEM) normalize your eye vector before calculating new coordinates in the fragment. if you don't normalize, the XY coords of the vector are going to be HUGE so your new texture coordinates are MASSIVE offsets.
try these shaders. they are very simple and work. you will have to add lighting after you get the parallax working
Vertex shader
attribute vec3 tangent;
attribute vec3 binormal;
uniform vec3 CAMERA_POSITION;
varying vec3 eyeVec;
void main()
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat3 TBNMatrix = mat3(tangent, binormal, gl_Normal);
eyeVec = CAMERA_POSITION - gl_Vertex.xyz;
eyeVec *= TBNMatrix;
}
fragment shader
uniform sampler2D basetex;
uniform sampler2D heightMap;
uniform vec2 scaleBias;
varying vec3 eyeVec;
void main()
{
float height = texture2D(heightMap, gl_TexCoord[0].st).r;
float v = height * scaleBias.r - scaleBias.g;
vec3 eye = normalize(eyeVec);
vec2 newCoords = texCoord + (eye.xy * v);
vec3 rgb = texture2D(basetex, newCoords).rgb;
gl_FragColor = vec4(rgb, 1.0);
}