0

I'm currently learning about shaders and graphics pipelines and I was wondering if a pixel shader could be used to create, for example, a triangle or a more complex shape like a zigzag.

Could this be done without the use of a vertex shader?

TheAuzzieJesus
  • 587
  • 9
  • 23
  • As noted by someone else, you can of course use ray-tracing to do pretty much anything with pixel shaders, but the performance and complexity is a major limitation. Still, on a modern high-end GPU you can do some pretty amazing stuff with it. You can also make use of [displacement maps](http://en.wikipedia.org/wiki/Displacement_mapping). – Chuck Walbourn Mar 16 '15 at 17:36

3 Answers3

2

Answer is yes! You can draw anything you want using pixel shader by implementing a ray Tracer. Here is a sample code:

Sample Ray Tracer

uniform vec3 lightposition;
uniform vec3 cameraposition;
uniform float motion;

struct Ray 
{
  vec3 org;
  vec3 dir;
};

struct Sphere 
{
  vec3 Center;
  float Radius;
  vec4 Color;
  float MatID;
  float id;
};


struct Intersection
{
  float t;
  vec3 normal;
  vec3 hitpos;
  vec4 color;
  float objectid;
  float materialID;
};


bool sphereIntersect(Ray eyeray, Sphere sp, inout Intersection intersection)
{

    float t1=0.0;
    eyeray.dir = normalize(eyeray.dir);
    float B = 2.0 *( ( eyeray.dir.x * (eyeray.org.x - sp.Center.x ) )+  ( eyeray.dir.y *(eyeray.org.y - sp.Center.y )) + ( eyeray.dir.z * (eyeray.org.z - sp.Center.z ) ));
    float C = pow((eyeray.org.x - sp.Center.x),2.0) + pow((eyeray.org.y - sp.Center.y),2.0) + pow((eyeray.org.z - sp.Center.z),2.0) - pow(sp.Radius,2.0);   
    float D = B*B - 4.0*C ;

    if(D>=0.0)
    {
        t1= (-B - pow(D, .5)) / 2.0;
        if (t1 < 0.0)
        {
            t1 = (-B + pow(D, .5)) / 2.0;
            if( t1 < 0.0)
                return false; 
            else
            {
                if (t1 > 1e-2 && t1 < intersection.t)
                { 
                    intersection.t = t1;
                    intersection.materialID = sp.MatID;
                    intersection.hitpos = eyeray.org + t1 * eyeray.dir;
                    intersection.normal = normalize(intersection.hitpos - sp.Center);
                    intersection.color = sp.Color;
                    intersection.objectid = sp.id;

                    return true;

                }
            }
        }
        else
        {
            if(t1 > 1e-2 && t1 < intersection.t)
            {
                intersection.t = t1;
                intersection.materialID = sp.MatID;
                intersection.hitpos = eyeray.org + t1 * eyeray.dir;
                intersection.normal = normalize(intersection.hitpos - sp.Center);
                intersection.color = sp.Color;
                intersection.objectid = sp.id;  

                return true; 
            }
        }
    }
    else
        return false; 
}   


void findIntersection(Ray ray, inout Intersection intersection)
{
    intersection.t = 1e10;
    intersection.materialID = 0.0;

    Sphere sp1 = Sphere(vec3(-2.0,0.0,-5.0),1.5,vec4(0.5, 0.1, 0.5, 1.0),1.0,1.0);
    Sphere sp2 = Sphere(vec3( 2.0,0.0,-5.0),1.5,vec4(0.5,0.5,0.1,1.0),1.0,2.0);
    Sphere sp3 = Sphere(vec3( 0.0,3.0,-5.0),1.5,vec4(0.1,0.5,0.5,1.0),1.0,3.0);

    sphereIntersect(ray, sp1, intersection);
    sphereIntersect(ray, sp2, intersection);
    sphereIntersect(ray, sp3, intersection);
}           

vec4 CalculateColor(vec4 ambient ,float shiness,vec3 intersection, vec3 normal);
Ray ReflectedRay(vec3 Normal,Ray EyeRay,vec3 intersection);
vec4 GetColor(Ray ray) 
{  
    Ray currentRay = ray;
    vec4 finalColor = vec4(0.0);

    for(int bounce = 1 ; bounce < 4 ; bounce++)
    {
        Intersection intersection;
        intersection.objectid = 0.0;
        findIntersection(currentRay, intersection);
        if (intersection.materialID == 0.0) // We could not find any object. We return the background color
            return finalColor;
        else if (intersection.materialID == 1.0) 
        {               
            vec3 lv = lightposition - intersection.hitpos;
            vec3 nlv = normalize(lv);

            Intersection shadowIntersection;
            Ray shadowRay = Ray(intersection.hitpos, nlv);
            shadowIntersection.objectid = intersection.objectid;

            findIntersection(shadowRay, shadowIntersection);

            if (shadowIntersection.t > length(lv) || shadowIntersection.t < 1)
            {
                finalColor = finalColor + float(1.0f/bounce) * CalculateColor(intersection.color, 100.0, intersection.hitpos, intersection.normal);;
            }
            else
            { 
                finalColor = finalColor + float(1.0f/bounce) * intersection.color;          
            }

            //currentRay = Ray(intersection.hitpos, reflect(ray.dir, intersection.normal));
            currentRay = ReflectedRay(intersection.normal,ray,intersection.hitpos);                             
        }
    }

    return finalColor;
}


Ray createRay(float ScreenWidth,float ScreenHeight)
{   
    Ray toret;
    toret.org = cameraposition;

    float left = -3.0;
    float bottom = -3.0;
    float screenZ = -3.0;


    float su = -3.0 + gl_FragCoord.x/ScreenWidth * 6; //gl_FragCoord gives you the current x and y component of your current pixel 
    float sv = -3.0 + gl_FragCoord.y/ScreenHeight * 6;  
    float sz = screenZ - cameraposition.z;

    toret.dir = normalize(vec3(su,sv,sz));


    //vec2 p =   (gl_FragCoord.xy/resolution) * 2 ;
    //toret.dir  =  normalize(vec3(p, -1.0));   
    return toret;
}

Ray ReflectedRay(vec3 Normal,Ray EyeRay,vec3 intersection)
{
    Ray reflection;



    reflection.dir = EyeRay.dir - 2 * Normal * dot(EyeRay.dir,Normal);
    reflection.org = intersection + reflection.dir * 0.01;

    return reflection;
}

vec4 CalculateColor(vec4 ambient ,float shiness,vec3 intersection, vec3 normal)
{
        //intensities
        vec3 Idifuse = vec3(1, 1, 1);  
        vec3 Iambient = vec3(0.8, 0.8, 0.8);
        vec3 Ispecular = vec3(1,1,1);

        vec3 kDifuse = vec3(0.5,0.5,0.5); //for difuse
        vec3 kSpecular = vec3(0.75, 0.6, 0.3); //for specular
        vec3 kAmbient = vec3(0.1, 0.2, 0.3); //for ambient

        //vec4 kSpecular = vec4(0.5,0.5,0.5,1.0);
        //vec4 kDifuse = vec4(0.5,0.5,0.5,1.0); 


        float ColorDifuse = max(dot(normal,lightposition),0.0) * kDifuse;


        //vector calculations
        vec3 l = normalize(lightposition - intersection); //light vector
        vec3 n = normalize(normal); // normalVector of point in the sea
        vec3 v = normalize(cameraposition - intersection); // view Vector 
        vec3 h = normalize(v + l); // half Vector


        vec3 difuse  = kDifuse * Idifuse * max(0.0, dot(n, l));
        vec3 specular = kSpecular * Ispecular * pow(max(0.0, dot(n, h)), shiness);
        vec3 color = ambient.xyz + difuse + specular;
        return vec4(color,1.0);

        gl_FragColor = vec4(color,1.0);


}


void main()
{
    if(lightposition == vec3(0.0,0.0,0.0))
        gl_FragColor = vec4(0.0,1.0,0.0,1.0);

    Ray eyeray = createRay(600.0,600.0);
    gl_FragColor = GetColor(eyeray);
}
Berke Cagkan Toptas
  • 1,034
  • 3
  • 21
  • 31
0

A useful technique is to use a fragment shader (I'm an OpenGL guy) with point sprites. Point sprites in OpenGL 3+ get rendered as squares of pixels, with the size of the square (gl_PointSize) set by the vertex shader.

In the fragment shader, gl_PointCoord has the x and y coords of this particular pixel within the square, from 0.0 to 1.0. So you can draw a circle by testing if gl_PointCoord.x and gl_PointCoord.y are both within the radius and discarding if not, a framed square by checking that .x and .y are with some distance of the edge, and so on. It's classic maths, define a function(x, y) which returns true for points within the shape you want, false if not.

The Orange book, OpenGL Shading Language 3rd edition, has some examples (which in turn come from RenderMan) of how to draw such shapes.

Hope this helps.

Hugh Fisher
  • 2,321
  • 13
  • 8
0

What you want is called procedural textures or procedural shading.

You can draw different shapes with a simple (and not so simple) math.

Take a look for some examples here: http://glslsandbox.com/

More on google.

Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61