Shape/texture backgrounds and transparency

I’m a little confused - when you add a texture to a 3D shape and don’t map the UVs correctly you have a false (black) background that fills any texture empty part of the 3D shape (see attached image of triangle - a photo has been added as texture). What is this black background? It’s not set by fill() and it’s not part of the texture so what is it and how can you access it to change it?

The goal is to make it transparent - so far have tried GL_BLEND in gl mode in Processing and post processing with a glsl shader like this:

if (textureColor.rgb == vec3(0.0, 0.0, 0.0))
{
  textureColor.a = 0.0;
}

gl_FragColor = vec4(textureColor.rgb, textureColor.a);

Which approach should work or is there a simpler way to initiate the shape with transparency?

If you draw a pixel black but with full transparency, the pixel is still drawn into the z-buffer which would prevent drawing any later pixels that should appear behind it. On the other hand, within a shader, you can discard a pixel which exits the shader without writing anything to either the color or z buffers.

In your case, rather than trying to not draw black pixels, which would fail if your texture also happens to contain black pixels, I would instead discard any pixels that fall outside of the desired texCoord range of 0 to 1 or wherever you want to have it set.

What it the cause of your mis-set UV coordinates? Is this a problem you could fix further back in the pipeline?

hi

If you draw a pixel black but with full transparency, the pixel is still drawn into the z-buffer

Yes but the black at the top of the triangle in the image I attached is not (I think) part of the texture image - if it was wouldn’t this be a continuation of the last pixel of the texture image, sort of like a slit scan camera does?

On the other hand, within a shader, you can discard a pixel which exits the shader without writing anything to either the color or z buffers.

This was the first thing I tried:

if (textureColor.rgb == vec3(0.0, 0.0, 0.0))
{
  discard;
}

gl_FragColor = textureColor.rgba;

It seemed to have no effect at all on the displayed black.

What it the cause of your mis-set UV coordinates? Is this a problem you could fix further back in the pipeline?

Well the cause is me, I’m doing this deliberately. Yes maybe the black to transparent issue could be fixed further back in the pipeline, perhaps there is a way of setting up a texture where these ‘out of bounds’ areas default to transparent instead of black. I remember doing something similar in max/msp years ago using opengl and you, at the very least, could define how textures repeated or didn’t if the texture was not mapped correctly on the 3D shape. What I don’t understand with Processing is what this black is - is it just some default for texture()?.

Ok so I have answered my own question, this ‘black’ is part of the texture. I put together a glsl contrast shader to be able to brighten the texture and you can see more than black - not clear on why most of it is black but perhaps that’s to do with the uv mapping.

I think I found a solution now to be able to drop out the ‘black’ for transparent. It’s not as precise as I wanted as it removes parts of the image as well but it works for me.

Below is solution sketch, shader and texture image.

Sketch

import com.jogamp.opengl.*;
com.jogamp.opengl.GL3 gl;

PImage currentphoto;
PShader contrast_shader;

void setup()
{
  size(1000, 800, OPENGL);
  
  background(255, 0, 0);

  currentphoto = loadImage("mars1.jpg");
  contrast_shader = loadShader("contrast.glsl");
  
  gl = GLContext.getCurrentGL().getGL3();

  noStroke();
  textureMode(NORMAL);
}

void draw()
{
  background(255, 0, 0);

  gl.glEnable(GL3.GL_BLEND);
  gl.glDisable(GL3.GL_DEPTH_TEST); 
  gl.glBlendFunc(GL3.GL_SRC_ALPHA, GL3.GL_ONE_MINUS_SRC_ALPHA);


  resetShader();
  contrast_shader.set("contrast", 0.5);
  shader(contrast_shader);
  

  fill(255, 0, 0);
  
  beginShape(TRIANGLE_FAN);
  texture(currentphoto);
  vertex(200, 100, -1, -1);
  vertex(480, 700, 1, 0);
  vertex(200, 500, 1, 1);
  vertex(200, 100, 0, 1);
  endShape();
}

GLSL shader called contrast.glsl

#ifdef GL_ES
precision mediump float;
#endif

#define PROCESSING_TEXTURE_SHADER

varying vec4 vertTexCoord;
uniform sampler2D texture;
uniform float contrast;


void main()
{
    vec4 textureColor = texture(texture, vertTexCoord.xy).rgba;
    
    highp float contrastScaled = 4.0 * contrast;
    
	if (textureColor.r < 0.2 && textureColor.g < 0.2 && textureColor.b < 0.2)
    {
        discard;
    }
    
    gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrastScaled + vec3(0.5)), (textureColor.r+textureColor.g+textureColor.b)/3.0 * 3.1 - 0.1);
}

Edit: You answered while I was experimenting and I missed it. Skip the first 2 paragraphs.

Processing only has two textureWrap modes, CLAMP and REPEAT, both of which should cover the entire triangle with texture pixels. If you are seeing any non-texture pixels “outside” of your texture coordinates, then are they the triangle edges in the current stroke color? Doesn’t quite look like it from your example, but I can’t see what else it could be. Did you set noStroke()?

Could you post a minimal code example of how you are rendering the geometry that shows the black out-of-range pixels?

If you want to not draw pixels outside of your texture coordinates, then you would have to create your own shaders, copying Processing’s default texture shaders, and tweak the fragment shader to only draw pixels that are within your texture coordinates while discarding the rest.

Skip the first 2 paragraphs.

Actually for some odd reason I had not spotted textureWrap() so useful.

If you want to not draw pixels outside of your texture coordinates, then you would have to create your own shaders, copying Processing’s default texture shaders

Good idea! I might look into this since I’m toying with shaders anyway.

Many thanks.