sampler2D and samplerCube in one shader - opengl

I'm trying to use sampler2D and samplerCube in one shader. I used to do this using struct for several sampler2D. But now I decided to stop putting them in the struct and noticed several features. If I put sampler2D into a struct, it is sufficient to bind the samplerCube 1 time. But if I put sampler2D outside the structure, I will have to bind samplerCube each time I draw each model. Below I give examples of pseudocode.
sampler2D into struct:
uniform samplerCube shadowMaps;
uniform struct Mapping {
sampler2D ambientMapping;
sampler2D diffuseMapping;
sampler2D specularMapping;
sampler2D normalMapping;
} mapping;
C++ pseudocode:
// somewhere in init
// samplerCube
glUniform1i(shadow, 4);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMapId);
// ...
// drawing models
for (size_t i = 0; i < MODELS_COUNT; i++) {
glUniform1i(model[i].ambientMapping, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, model[i].texturesIds[0]);
glUniform1i(model[i].diffuseMapping, 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, model[i].texturesIds[1]);
// analogically for specular and normal
// model
}
sampler2D outside struct:
uniform samplerCube shadowMaps;
uniform sampler2D ambientMapping;
uniform sampler2D diffuseMapping;
uniform sampler2D specularMapping;
uniform sampler2D normalMapping;
C++ pseudocode:
// drawing models
for (size_t i = 0; i < MODELS_COUNT; i++) {
glUniform1i(model[i].ambientMapping, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, model[i].texturesIds[0]);
glUniform1i(model[i].diffuseMapping, 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, model[i].texturesIds[1]);
// analogically for specular and normal
// samplerCube
glUniform1i(shadow, 4);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMapId);
// model
}
Why in the second case I should everytime do glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMapId)? And what is the best way to do it? What will be more productive?

Related

opengl + emscripten textures not getting displayed

i am tring to display textures using opengles + emscripten, but all i am getting are black triangles.
output image
my vertex shader:
attribute vec3 position;
attribute vec4 color;
attribute vec3 normal;
attribute vec2 uv;
varying vec4 v_color;
varying vec3 v_normal;
varying vec2 v_uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
highp mat4 transpose(in highp mat4 inMatrix) {
highp vec4 i0 = inMatrix[0];
highp vec4 i1 = inMatrix[1];
highp vec4 i2 = inMatrix[2];
highp vec4 i3 = inMatrix[3];
highp mat4 outMatrix = mat4(
vec4(i0.x, i1.x, i2.x, i3.x),
vec4(i0.y, i1.y, i2.y, i3.y),
vec4(i0.z, i1.z, i2.z, i3.z),
vec4(i0.w, i1.w, i2.w, i3.w)
);
return outMatrix;
}
void main()
{
v_color = color;
v_normal = normal;
v_uv = uv;
gl_Position = projection * view * transpose(model) * vec4(position.xyz, 1.0);
}
fragment shader:
precision mediump float;
varying vec4 v_color;
varying vec3 v_normal;
varying vec2 v_uv;
uniform sampler2D tex;
void main()
{
// gl_FragColor = v_color;
gl_FragColor = texture2D(tex, v_uv.xy);
}
texture create function:
void IG::Texture::create(unsigned char* image,
uint32_t width,
uint32_t height,
uint32_t channels)
{
if(image == nullptr)
{
std::cout<<"Texture creation failed! invalid image data.."<<std::endl;
return;
}
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glGenTextures(1, &ID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ID);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, attribs.uv_mode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, attribs.uv_mode);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, attribs.min_filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, attribs.mag_filter);
glTexImage2D(GL_TEXTURE_2D,
attribs.mip_level,
GL_RGB,
width,
height,
attribs.border,
GL_RGB,
GL_UNSIGNED_BYTE,
image);
// glGenerateMipmap(GL_TEXTURE_2D);
}
here attribs is a struct with values:
uv_mode(GL_REPEAT),
min_filter(GL_LINEAR_MIPMAP_LINEAR),
mag_filter(GL_LINEAR),
mip_level(0),
border(0)
i have verified that the image is valid using stb_image.
inside the draw loop all triangles are iterated and drawn using this call:
void Renderer::draw_objects(){
for(auto& v : gl_objects){
auto &shape = v.second;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shape.tex.ID);
shader->set_mat4("model", shape.transform);
glBindVertexArray(shape.VAO);
glUniform1i(shape.tex.samplerLoc, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}
i am taking references from these links learopengl emscripten opengles examples
i am unable to debug what i am doing wrong here. what could be the issue here?
Your problem come from the missing mipmaps, it try to render a specific mipmaps that is not created, resulting in black pixels.
A proper call to glGenerateMipmap after glTexImage2D would solve the issue.
If you don't generate mipmaps mipmaps (with glGenerateMipmap) you must use one of the non mipmap minifying functions (GL_NEAREST or GL_LINEAR). If you use a mipmap minification function, the texture would be "Mipmap Incomplete".
Eiter use min_filter(GL_LINEAR) or call glGenerateMipmap(GL_TEXTURE_2D);.

How to modify color values of sampled texture in OpenGL fragment shader

I try to create simple computer tomography viewer with OpenGL, data is 1D float array that represents single slice.
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_FLOAT, data);
Question
How to modify the colors/float values in fragment shader for the windowing purposes
So displaying all values above some treshold as white and all below as black and the rest as greys between
my fragment shader
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
FragColor = texture(ourTexture, TexCoord);
}
All works well yet I have some problems
well simply by combining thresholding with linear interpolation something like this:
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
vec4 col=texture(ourTexture, TexCoord); // input color
float t0=0.25,t1=0.75; // thresholds
float t=length(col.rgb)/1.73205081; // /sqrt(3) ... parameter is intensity of color
t=(t-t0)/(t1-t0); // dynamic range <t0,t1> -> <0,1>
t=max(t,0.0); // cut off unused range
t=min(t,1.0);
FragColor = vec4(t,t,t,col.a);
}
Beware I did not test it as I wrote this directly in answer editor so there might be some hidden typos and too lazy to create MCVE from scratch...

When using texture arrays, why do I not have to bind the sampler to the shader?

I am creating an array of textures using GL_TEXTURE_2D_ARRAY in my code:
// Load all images ito opengl
unsigned int width, height;
std::vector<unsigned char> textures;
int num = 0;
for ( auto each : image_list )
{
// Load PNG
std::vector<unsigned char> buffer, this_texture;
lodepng::load_file(buffer, each.string().c_str());
auto lode_error = lodepng::decode(this_texture, width, height, buffer);
if (lode_error)
{
LOG_ERROR("lodepng has reported this error: " + std::string(lodepng_error_text(lode_error)));
return false;
}
m_indexes.insert(std::make_pair(each.filename().string(), num));
textures.insert(textures.end(), this_texture.begin(), this_texture.end());
num++;
}
// Active texture
glActiveTexture(GL_TEXTURE0);
// Generate texture
glGenTextures(1, &m_texture_id);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_id);
// Send pixels
glTexImage3D(GL_TEXTURE_2D_ARRAY,
0,
GL_RGBA,
width, height,
image_list.size(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
textures.data());
// Set options
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Here are the shaders I am using:
Vertex Shader
#version 430 core
/* layouts */
layout (location = 0) in vec3 in_vertex;
layout (location = 1) in vec2 in_uv;
layout (location = 2) in vec4 in_tint;
layout (location = 3) in mat4 in_model;
layout (location = 7) in vec3 in_scale;
layout (location = 8) in float in_textured_index;
/* uniforms */
uniform mat4 ortho;
uniform mat4 view;
/* outputs */
out vec4 tint;
out vec2 uv;
out float textured_index;
void main()
{
mat4 mvp = ortho * view * in_model;
gl_Position = mvp * vec4(in_vertex * in_scale, 1.0);
tint = in_tint;
uv = in_uv;
textured_index = in_textured_index;
}
Fragment Shader
#version 430 core
/* inputs from vertex shader */
in vec4 tint;
in vec2 uv;
in float textured_index;
/* output to GPU */
out vec4 fragment;
/* texture sampler */
uniform sampler2DArray sampler_unit;
void main()
{
fragment = texture(sampler_unit, vec3(uv.xy, textured_index)).rgba;
fragment = fragment * tint;
}
Code to bind the texture array:
void ArrayTextures::attach()
{
if (glIsTexture(m_texture_id)){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_id);
}
}
What I have noticed, is that I do not have to attach the texture unit or the texture id to my shader, as long as the texture is bound with above function. It just works. I would like to understand why. In OpenGL 3.X, you have to bind the sampler to your shader before you can use it. Is there any automatism behind the scenes, that I am not aware of? Since I have a 5700XT, may this be an AMD specific oddity? What is the correct way here, so I can be sure it also works on NVIDIA?
This has nothing to do with the sampler type. The binding between the texture object and the texture sampler is the texture unit. The texture object must be bound to a texture unit, and the texture unit number must be set to the texture sampler uniform.
In GLSL almost everything is initialized with 0 respectively 0.0 by default. Therefore the default Binding point is 0. If the texture is bound to the texture unit 0 (GL_Texture0), it is not necessary to set the texture sampler uniform as it is 0 by default.

How do I get textures to work in OpenGL?

I'm using the tutorials on http://arcsynthesis.org/gltut/ to learn OpenGL, it's required, I have to use it. Mostly I want to apply the textures from Tutorial 15 onto objects in tutorial 7 (world with UBO).
For now it seemed like the textures only work when mipmaps are turned on. This comes with a downside: The only mipmap used is the one with an index of zero, and that's the 1 colored 1x1 pixel one. I tried setting the minimum level of a mipmap higher or turning off mipmaps entirely, but even that doesn't fix thing, because then everything turns pitch black. Now I'll list the most important parts of my program
EDIT: I guess I'll add more details...
The vertex shader has something like this:
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
layout(location = 2) in vec3 normal;
//Added these later
layout(location = 5) in vec2 texCoord;
out vec2 colorCoord;
smooth out vec4 interpColor;
out vec3 vertexNormal;
out vec3 modelSpacePosition;
out vec3 cameraSpacePosition;
uniform mat4 worldToCameraMatrix;
uniform mat4 modelToWorldMatrix;
uniform mat3 normalModelToCameraMatrix;
uniform vec3 dirToLight;
uniform vec4 lightIntensity;
uniform vec4 ambientIntensity;
uniform vec4 baseColor;
uniform mat4 cameraToClipMatrix;
void main()
{
vertexNormal = normal;
vec3 normCamSpace = normalize(normalModelToCameraMatrix * vertexNormal);
cameraSpacePosition = normCamSpace;
float cosAngIncidence = dot(normCamSpace, dirToLight);
cosAngIncidence = clamp(cosAngIncidence, 0, 1);
modelSpacePosition.x = position.x;
modelSpacePosition.y = position.y;
modelSpacePosition.z = position.z;
vec4 temp = modelToWorldMatrix * position;
temp = worldToCameraMatrix * temp;
gl_Position = cameraToClipMatrix * temp;
interpColor = ((lightIntensity * cosAngIncidence) + (ambientIntensity)) * baseColor;
colorCoord= texCoord ;
}
The fragment shader like this:
#version 330
in vec3 vertexNormal;
in vec3 modelSpacePosition;
smooth in vec4 interpColor;
uniform vec3 modelSpaceLightPos;
uniform vec4 lightIntensity2;
uniform vec4 ambientIntensity2;
out vec4 outputColor;
//Added later
in vec2 colorCoord;
uniform sampler2D colorTexture;
void main()
{
vec3 lightDir2 = normalize(modelSpacePosition - modelSpaceLightPos);
float cosAngIncidence2 = dot(normalize(vertexNormal), lightDir2);
cosAngIncidence2 = clamp(cosAngIncidence2, 0, 1);
float light2DistanceSqr = dot(modelSpacePosition - modelSpaceLightPos, modelSpacePosition - modelSpaceLightPos);
//added
vec4 texture2 = texture(colorTexture, colorCoord);
outputColor = ((ambientIntensity2 + (interpColor*2))/4) +
((((interpColor) * lightIntensity2/200 * cosAngIncidence2) + (ambientIntensity2* interpColor ))
/( ( sqrt(light2DistanceSqr) + light2DistanceSqr)/200 ));
//No outputColor for texture testing
outputColor = texture2 ;
}
}
Those were both shaders. And here are the parts added to the .cpp:
#include <glimg/glimg.h>
#include "../framework/directories.h"
[...]
const int g_colorTexUnit = 0;
GLuint g_checkerTexture = 0;
And here's the loader for the texture:
void LoadCheckerTexture()
{
try
{
std::string filename(LOCAL_FILE_DIR);
filename += "checker.dds";
std::auto_ptr<glimg::ImageSet>
pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str()));
glGenTextures(1, &g_checkerTexture);
glBindTexture(GL_TEXTURE_2D, g_checkerTexture);
glimg::SingleImage image = pImageSet->GetImage(0, 0, 0);
glimg::Dimensions dims = image.GetDimensions();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, dims.width, dims.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image.GetImageData());
glBindTexture(GL_TEXTURE_2D, 0);
}
catch(std::exception &e)
{
printf("%s\n", e.what());
throw;
}
}
Naturally I've got this in void init():
LoadCheckerTexture();
And then when rendering the object:
glActiveTexture(GL_TEXTURE0 + g_colorTexUnit);
glBindTexture(GL_TEXTURE_2D,g_checkerTexture);
g_pLeftMesh->Render();
glBindSampler(g_colorTexUnit, 0);
glBindTexture(GL_TEXTURE_2D, 0);
With all of this, I get put pitch black for everything, however when I change the outputColor equation into "texture + outputColor;", everything looks normal. I have no idea what I'm doing wrong here. A friend tried to help me, we removed some unnecessairy stuff, but we got nothing running.
Ok guys, I've worked on this whole thing, and did manage to somehow get it running. First off I had to add samplers:
GLuint g_samplers;
//Add Later
void CreateSamplers()
{
glGenSamplers(1, &g_samplers);
glSamplerParameteri(g_samplers, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(g_samplers, GL_TEXTURE_WRAP_T, GL_REPEAT);
//Linear mipmap Nearest
glSamplerParameteri(g_samplers, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(g_samplers, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
I also added this to the file thing:
glimg::OpenGLPixelTransferParams xfer = glimg::GetUploadFormatType(pImageSet->GetFormat(), 0);
glimg::SingleImage image = pImageSet->GetImage(0, 0, 0);
glimg::Dimensions dims = image.GetDimensions();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims.width, dims.height, 0,
xfer.format, xfer.type, image.GetImageData());
The xfer variable does get the format and type adjusted to the dds.
Also the render code got turned into this:
//Added necessary
glActiveTexture(GL_TEXTURE0 + g_colorTexUnit);
glBindTexture(GL_TEXTURE_2D,g_checkerTexture);
glBindSampler(g_colorTexUnit, g_samplers);
g_pLeftMesh->Render();
glBindSampler(g_colorTexUnit, 0);
glBindTexture(GL_TEXTURE_2D, 0);
And of course at the end of init() I needed to add the CreateSamplers thing:
//Added this later
LoadCheckerTexture();
CreateSamplers();
I'm sorry for all the trouble with all this, but guess OpenGL really is just this confusing and it was just dumb luck that I got it right. Just posting this so that people know
Your fail to add textures may be caused by:
Have you add texture coordinates to objects? (this is the most probable cause, because you are adding textures to non textured tutorial), add textures to VAO.
Did you add uniform textureunit (Sampler2D)? (it must be uniform, else texturing will not work properly)
Is your texture loaded,binded,enabled (GL_TEXTURE_2D) ?
Is your active texture unit - 0? if not change layout/multitexture coords or set active texture 0
This two codes are simple texturing shaders (texture unit 0) no special things (like light,blend,bump,...):
tm_l2g is transformation local obj space -> world space (Modelview)
tm_g2s is transformation world space -> screen space (Projection)
pos are vertex coordinates
txt are texture coordinates
col are colors
Do not forget to change uniform names and layout locations to yours.
Vertex:
//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
uniform mat4x4 tm_l2g;
uniform mat4x4 tm_g2s;
layout(location=0) in vec3 pos;
layout(location=1) in vec4 col;
layout(location=2) in vec2 txr;
out smooth vec4 pixel_col;
out smooth vec2 pixel_txr;
//------------------------------------------------------------------
void main(void)
{
vec4 p;
p.xyz=pos;
p.w=1.0;
p=tm_l2g*p;
p=tm_g2s*p;
gl_Position=p;
pixel_col=col;
pixel_txr=txr;
}
//------------------------------------------------------------------
fragment:
//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
in smooth vec4 pixel_col;
in smooth vec2 pixel_txr;
uniform sampler2D txr_texture0;
out layout(location=0) vec4 frag_col;
//------------------------------------------------------------------
void main(void)
{
vec4 col;
col=texture(txr_texture0,pixel_txr.st);
frag_col=col*pixel_col;
}
//------------------------------------------------------------------
[edit1] CPU old style OpenGL render code (initializations are not included its only render code they can be found here)
//------------------------------------------------------------------
// set modelview,projection,textures,bind GLSL programs...
GLfloat a=10.0,z=0.0;
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
// textured quad
glTexCoord2f(0.0,0.0); glVertex3f(-a,-a,z);
glTexCoord2f(0.0,1.0); glVertex3f(-a,+a,z);
glTexCoord2f(1.0,1.0); glVertex3f(+a,+a,z);
glTexCoord2f(1.0,0.0); glVertex3f(+a,-a,z);
// reverse order quad to be shore that at least one passes by CULL_FACE
glTexCoord2f(1.0,0.0); glVertex3f(+a,-a,z);
glTexCoord2f(1.0,1.0); glVertex3f(+a,+a,z);
glTexCoord2f(0.0,1.0); glVertex3f(-a,+a,z);
glTexCoord2f(0.0,0.0); glVertex3f(-a,-a,z);
glEnd();
//------------------------------------------------------------------
[edit2] ok here goes VAO/VBO render code,...
//------------------------------------------------------------------------------
// enum of VBO locations (it is also your layout location) I use enums for simple in code changes
enum _vbo_enum
{
_vbo_pos=0, // glVertex
_vbo_col, // glColor
_vbo_tan, // glNormal
_vbo_unused0, // unused (at least i dont see anything at this location in your code)
_vbo_unused1, // unused (at least i dont see anything at this location in your code)
_vbo_txr, // glTexCoord
_vbos
};
//------------------------------------------------------------------------------
// 'global' names and size for OpenGL mesh in VAO/VBO ... similar ot texture names/handles
GLuint vao[1],vbo[_vbos],num_pnt=0;
//------------------------------------------------------------------------------
void VAO_init_cube() // call this before VAO use,...but after OpenGL init !
{
//[1] first you need some model to render (mesh), here is a simple cube
// size,position of cube - change it that it is visible in your scene
const GLfloat a=1.0,x=0.0,y=0.0,z=0.0;
// cube points 3f x,y,z
GLfloat mesh_pos[]=
{
x-a,y-a,z-a,x-a,y+a,z-a,x+a,y+a,z-a,x+a,y-a,z-a,
x-a,y-a,z+a,x-a,y+a,z+a,x+a,y+a,z+a,x+a,y-a,z+a,
x-a,y-a,z-a,x-a,y-a,z+a,x+a,y-a,z+a,x+a,y-a,z-a,
x-a,y+a,z-a,x-a,y+a,z+a,x+a,y+a,z+a,x+a,y+a,z-a,
x-a,y-a,z-a,x-a,y+a,z-a,x-a,y+a,z+a,x-a,y-a,z+a,
x+a,y-a,z-a,x+a,y+a,z-a,x+a,y+a,z+a,x+a,y-a,z+a,
};
// cube colors 3f r,g,b
GLfloat mesh_col[]=
{
0.0,0.0,0.0,0.0,1.0,0.0,1.0,1.0,0.0,1.0,0.0,0.0,
0.0,0.0,1.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,1.0,
0.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0,0.0,
0.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,
0.0,0.0,0.0,0.0,1.0,0.0,0.0,1.0,1.0,0.0,0.0,1.0,
1.0,0.0,0.0,1.0,1.0,0.0,1.0,1.0,1.0,1.0,0.0,1.0,
};
// cube normals 3f x,y,z
GLfloat mesh_tan[]=
{
-0.6,-0.6,-0.6,-0.6,+0.6,-0.6,+0.6,+0.6,-0.6,+0.6,-0.6,-0.6,
-0.6,-0.6,+0.6,-0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,-0.6,+0.6,
-0.6,-0.6,-0.6,-0.6,-0.6,+0.6,+0.6,-0.6,+0.6,+0.6,-0.6,-0.6,
-0.6,+0.6,-0.6,-0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,+0.6,-0.6,
-0.6,-0.6,-0.6,-0.6,+0.6,-0.6,-0.6,+0.6,+0.6,-0.6,-0.6,+0.6,
+0.6,-0.6,-0.6,+0.6,+0.6,-0.6,+0.6,+0.6,+0.6,+0.6,-0.6,+0.6,
};
// cube texture coords 2f s,t
GLfloat mesh_txr[]=
{
0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
0.0,0.0,0.0,1.0,1.0,1.0,1.0,0.0,
};
// init VAO/VBO
glGenVertexArrays(1,vao); // allocate 1 x VAO
glGenBuffers(_vbos,vbo); // allocate _vbos x VBO
// copy mesh to VAO/VBO ... after this you do not need the mesh anymore
GLint i,sz,n; // n = number of numbers per 1 entry
glBindVertexArray(vao[0]);
num_pnt=sizeof(mesh_pos)/(sizeof(GLfloat)*3); // num of all points in mesh
i=_OpenGLVAOgfx_pos; n=3; sz=sizeof(GLfloat)*n;
glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_pos,GL_STATIC_DRAW);
glEnableVertexAttribArray(i);
glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);
i=_OpenGLVAOgfx_col; n=3; sz=sizeof(GLfloat)*n;
glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_col,GL_STATIC_DRAW);
glEnableVertexAttribArray(i);
glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);
i=_OpenGLVAOgfx_tan; n=3; sz=sizeof(GLfloat)*n;
glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_tan,GL_STATIC_DRAW);
glEnableVertexAttribArray(i);
glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);
i=_OpenGLVAOgfx_txr; n=2; sz=sizeof(GLfloat)*n;
glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
glBufferData(GL_ARRAY_BUFFER,sz*num_pnt,mesh_txr,GL_STATIC_DRAW);
glEnableVertexAttribArray(i);
glVertexAttribPointer(i,n,GL_FLOAT,GL_FALSE,0,0);
glBindVertexArray(0);
}
//------------------------------------------------------------------------------
void VAO_draw() // call this to draw your mesh,... need to enable and bind textures,... before use
{
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBindVertexArray(vao[0]);
glEnableVertexAttribArray(_vbo_pos);
glEnableVertexAttribArray(_vbo_col);
glEnableVertexAttribArray(_vbo_tan);
glDisableVertexAttribArray(_vbo_unused0);
glEnableVertexAttribArray(_vbo_txr);
glDrawArrays(GL_QUADS,0,num_pnt);
glDisableVertexAttribArray(_vbo_pos);
glDisableVertexAttribArray(_vbo_col);
glDisableVertexAttribArray(_vbo_tan);
glDisableVertexAttribArray(_vbo_unused0);
glDisableVertexAttribArray(_vbo_unused1);
glDisableVertexAttribArray(_vbo_txr);
glBindVertexArray(0);
}
//------------------------------------------------------------------------------
void VAO_exit() // clean up ... call this when you do not need VAO/VBO anymore
{
glDisableVertexAttribArray(_vbo_pos);
glDisableVertexAttribArray(_vbo_col);
glDisableVertexAttribArray(_vbo_tan);
glDisableVertexAttribArray(_vbo_unused0);
glDisableVertexAttribArray(_vbo_unused1);
glDisableVertexAttribArray(_vbo_txr);
glBindVertexArray(0);
glDeleteVertexArrays(1,vao);
glDeleteBuffers(_vbos,vbo);
}
//------------------------------------------------------------------------------
[edit3] if you are win32/64 user you can try my IDE for GLSL
It is very simple and easy to use, but cannot change texture/attrib locations. Press [F1] for help,... [F9] for run [F10] for return to normal OpenGL mode. Also txt-editor is little buggy sometimes but it is enough for my purpose.
GLSL IDE

Alternate gl_FragColor values from two textures in GLSL

I have two textures, cloud and hill, each with 512 x 512 size, and i intend to create a gl_FragColor output which will obtain the pixel values from the previous textures. In this case, i want to obtain the 1st pixel in gl_FragColor from the 1st pixel in the 1st texture, the 2nd pixel in the gl_FragColor from the 2nd pixel in the 2nd texture, the 3rd pixel in gl_FragColor from the 3rd pixel in the 1st texture an so on. Here is my fragment shader code:
uniform sampler2D tex0;
uniform sampler2D tex1;
void main() {
vec4 cloud = texture2D(tex0, gl_TexCoord[0].st);
vec4 hill = texture2D(tex1, gl_TexCoord[0].st);
for (int i=0;i<512;i++) {
for (int j=0;j<512;j++) {
if ( j%2 == 0)
gl_FragColor = cloud;
else
gl_FragColor = hill;
}
}
}
Here's the texture unit setup:
t1 = loadTexture("pY.raw", 512, 512);
t2 = loadTexture("pZ.raw", 512, 512);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, t2);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, t1);
glEnable(GL_TEXTURE_2D);
And here is the uniform setup:
glUseProgram(program);
GLuint t1Location = glGetUniformLocation(program, "tex0");
GLuint t2Location = glGetUniformLocation(program, "tex1");
glUniform1i(t1Location, 0);
glUniform1i(t2Location, 1);
The problem is, the output for the program is only the hill texture, and i don't know how to fix this. Any suggestion?
You don't need to do any iterations in your shader. Pixel shader will be called once for every pixel in your object. Instead use gl_TexCoord[0] to get current texture coordinates. Your code should look something like that:
uniform sampler2D tex0;
uniform sampler2D tex1;
void main()
{
vec4 cloud = texture2D(tex0, gl_TexCoord[0].st);
vec4 hill = texture2D(tex1, gl_TexCoord[0].st);
if ( int(gl_TexCoord[0].x*512)%2 == 0)
gl_FragColor = cloud;
else
gl_FragColor = hill;
}
}
This one should work, even with older opengl:
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D tex0;
uniform sampler2D tex1;
void main(void)
{
if((gl_FragCoord/32.0- vec4(ivec4(gl_FragCoord/32.0))).x<0.5)
gl_FragColor = texture2D(tex0, gl_FragCoord.xy/512.0);
else
gl_FragColor = texture2D(tex1, gl_FragCoord.xy/512.0);
}
You can try it out with WebGL at: http://www.iquilezles.org/apps/shadertoy/