Binding textures inside shaders - opengl

I am coding a wavefront (.obj) loader with VBO's.
When "usemtl" is called, I am thinking about sending textureID together with vertex, texCoord and normal data.
With that texture ID can I bind the texture inside vertex/fragment shader without calling glBindTexture?

With that texture ID can I bind the texture inside vertex/fragment shader without calling glBindTexture?
No. Textures are not bound to shaders; they're bound to the context.
If you want to get technical, NV_bindless_texture allows such functionality, but that's NVIDIA-specific.

that is problem with materials in general, they need to be switched before rendering geometry.
simplest way is:
foreach object in renderQueue
set_material()
draw_geometry()
and of course we get into some troubles when one objects has to be rendered with two different materials. Another problem is with performance, you usually would sort objects by materials and save the switching (of textures, shaders and other data)

Related

How to render multiple objects that can each have multiple shaders in OpenGL 3.3?

Im trying to make a 3D renderer with OpenGL using c++, well, so far I have a Scene class that contains a list of Objects and Materials objects (I also have classes for those and I written my code so an object can have multiple shaders (every shader will be able to affect a group of vertices in an object) but now I'm trying to find a good way to send all that information to openGL.
I've seen people suggest taking everything that uses the same shader and rendering that at once, and do the same for every shader, well If I understood well enough,but is that a good idea if you can get the same shaders included in different objects, if I merged every vert that has shader A for example, won't it hurt that that group contains verts of separate objects when I try to draw them at once ? And if I take each object and separate each object according to their shaders, so for the rendering I would take Object A then split into its shader groups, then draw shadergroup1 in object1 then shader group2 in object 2 and so on.. Won't that be too many draw calls too.
What strategy do you recommend to accomplish that ?
The first things I recommend is, that you stop thinking in terms of "objects", as far as the rendering process is concerned. When rendering the only sensible grouping are drawing batches (of a certain primitive, points, lines, triangles) for which the same rendering steps (render pipeline) is executed. The modern rendering APIs that were released over the past months (Vulkan, DirectX 12 and Metal) make this explicit.
When rendering your scene the recommended strategy is to iterate over all your objects, split them into render pipeline groups and perform a single drawing batch call once for each primitive-by-pipeline group. The overall goal should be to minimize the total number of drawing calls made.
If you are using OpenGL 3.3, you are using Vertex Array Objects (VAO) and Vertex Buffer Objects (VBO). You have an object, a table for example, which can have three (or more or less) VBO:s, one for vertex data, one for normal data and one for texture coordinate data. You enclose your VBO:s of that table inside one VAO. So every object have its own VAO stored in a GPU memory.
When you want to render your objects or a part of them, you bind one of your shaders at use and call those VAO:s you want to render by that shader. It may be important that you render right objects on right order and use right shaders (of course!) on each VAO.

OpenGL render .obj files with multiple material and textures

I'm writing a parser for .obj files with multiple materials and groups (so I'm also parsing usemtl and material files). I can load and render the vertices. How do I deal with different textures and materials?
Do I render each material one by one or having a giant shader to choose ID? And how do I store different textures on the GPU buffer? (Currently I am using GL_TEXTURE_2D_ARRAY but they must have the same size.
So, to handle different materials, each object has the material specifications like ambient_color, diffuse_color, and specular_color. You simply, pass these values as uniform to fragment shader and render the object with different material specs.
Also, you can use 128 textures simultaneously in one fragment shader, so you can render an object with more than texture. But most of the time an object is made of groups and each group has just one texture, so you just need a sampler2D object in fragment shader, just the uniform values which you are passing for the texture will change.
Best way to handle this efficiently is to render the groups with the same texture together, so prevent lots of texture changes.

How to apply a vertex shader to all vertices in a scene in OpenGL?

I'm working on a small engine in OpenTK right now, and I've got shaders working so far. I wonder though , how it is possible to apply a shader to an entire scene!?. I've seen this done in minecraft for example, where someone created a shader that warped the entire scene. But since every object is rendered with its own shader active, how would I achieve this?
You seem to be referring to a technique called post processing. The way it works is that you first render the entire scene to a texture using the shaders you already have. You can then render this texture to the screen using a fragment shader to apply various effects like motion blur, warping or depth of field.
"But since every object is rendered with its own shader active"
That's not how OpenGL works. In fact there's no such thing as "models" (what you probably mean by "object") in OpenGL. OpenGL draws primitives (points, lines and triangles) one at a time. Furthermore there's no hard association between a set of primitives and the shaders being used.
It's trivial to just bind a single shader program at the beginning of a batch and every primitive of that batch is subjected to this shader. If the batch consists of the whole scene, then the whole scene uses that shader.
AFAIK, you can only bind one vertex shader at a time.
What you may want to try is to render to a texture first then rerender the texture onto the screen but applying some changes to it (warping it for example). You can also extract the depth buffer and use it if you have a more complex change that you want to apply.
If you bind the shader you want before the render loop, it would effect all items until you un-bind it (i.e. binding id #0) or disable GL_TEXTURE_2D via glEnable()/glDisable().

OpenGL rendering with multiple textures

Is there a way in OpenGL to render a vertex buffer using multiple independent textures in VRAM without manually binding them (i.e. returning control to the CPU) in between?
Edit: So I'm currently rendering objects with multiple textures by rendering with a single texture, binding a new texture, and repeating, until everything is done. This is slow and requires returning control to CPU and making syscalls for every texture. Is there a way to avoid this switching, and make multiple textures available to the shaders to choose based on vertex data?
As mentioned in the comments on the question, glActiveTexture is the key - samplers in GLSL bind to texture units (e.g. GL_TEXTURE0), not specific texture targets (e.g. GL_TEXTURE2D), so you can bind a GL_TEXTURE2D texture under glActiveTexture(GL_TEXTURE0), another under glActiveTexture(GL_TEXTURE1), and then bind your GLSL sampler2D values to be 0, 1, etc. (NB: do not make your sampler2D values GL_TEXTURE0, GL_TEXTURE1, etc. - they are offsets from GL_TEXTURE0).

Drawing geometry in opengl

Taking the standard opengl 4.0+ functions & specifications into consideration; i've seen that geometries and shapes can be created in either two ways:
making use of VAO & VBO s.
using shader programs.
which one is the standard way of creating shapes?? are they consistent with each other? or they are two different ways for creating geometry and shapes?
Geometry is loaded into the GPU with VAO & VBO.
Geometry shaders produce new geometry based on uploaded. Use them to make special effects like particles, shadows(Shadow Volumes) in more efficient way.
tessellation shaders serve to subdivide geometry for some effects like displacement mapping.
I strongly (like really strongly) recommend you reading this http://fgiesen.wordpress.com/2011/07/09/a-trip-through-the-graphics-pipeline-2011-index/
VAOs and VBOs how about what geometry to draw (specifying per-vertex data). Shader programs are about how to draw them (which program gets applied to each provided vertex, each fragment and so on).
Let's lay out the full facts.
Shaders need input. Without input that changes, every shader invocation will produce exactly the same values. That's how shaders work. When you issue a draw call, a number of shader invocations are launched. The only variables that will change from invocation to invocation within this draw call are in variables. So unless you use some sort of input, every shader will produce the same outputs.
However, that doesn't mean you absolutely need a VAO that actually contains things. It is perfectly legal (though there are some drivers that don't support it) to render with a VAO that doesn't have any attributes enabled (though you have to use array rendering, not indexed rendering). In which case, all user-defined inputs to the vertex shader (if any) will be filled in with context state, which will be constant.
The vertex shader does have some other, built-in per-vertex inputs generated by the system. Namely gl_VertexID. This is the index used by OpenGL to uniquely identify this particular vertex. It will be different for every vertex.
So you could, for example, fetch geometry data yourself based on this index through uniform buffers, buffer textures, or some other mechanism. Or you can procedurally generate vertex data based on the index. Or something else. You could pass that data along to tessellation shaders for them to tessellate the generated data. Or to geometry shaders to do whatever it is you want with those. However you want to turn that index into real data is up to you.
Here's an example from my tutorial series that generates vertex data from nothing more than an index.
i've seen that geometries and shapes can be created in either two ways:
Not either. In modern OpenGL-4 you need both data and programs.
VBOs and VAOs do contain the raw geometry data. Shaders are the programs (usually executed on the GPU) that turn the raw data into pixels on the screen.
Vertex shaders can be used to displace vertices, or to generate them from a builtin formula and the vertex index, which is available as a built in attribute in later open gl versions.
The difference between vertex and geometry shaders is that vertex shader is a 1:1 mapping, while geometry shader can create more vertices -- can be utilized in automatic Level of Detail generation for e.g. NURBS or perlin noise based terrains etc.