예제 #1
0
RGBAPixel GeometricObject::rayTrace(PointLight& lightSrc, Point3D& pt, Ray& viewRay, vector<GeometricObject*>& shapes){
    
    RGBAPixel color = material.color;
    if(texture != NULL)
        color = *mapToTexture(pt);
    
    Vector3D dir(lightSrc.o,pt);
    dir.normalize();
    
    Point3D tempPt(pt+dir.reflect()*0.01);
    Ray backtraceRay(tempPt,dir.reflect(), "shadow"); //from hit point on shape to light source
    double tHitLight = lightSrc.o.distance(pt);
    bool shadow = false;
    
    Point3D trash(0,0,0);
    for(int i = 0; i < shapes.size(); i++){
        if(shapes[i]->isLightSrc)
            continue;
        double tHitAnotherShape = shapes[i]->hit(backtraceRay,trash);
        if(tHitAnotherShape < tHitLight && tHitAnotherShape > 0){
            shadow = true;
            break;
        }
    }
    
    //pt's intersection with viewRay and geometry
    Vector3D n(this->getNormal(pt));
    n.normalize();
    
    double r = 0.0;
    double g = 0.0;
    double b = 0.0;
    
    //Ambient Lighting
    r += 0.04 * 30;
    g += 0.04 * 30;
    b += 0.04 * 30;
    
    RGBAPixel temp(r*color.red, g*color.green ,b*color.blue);
    
    if(shadow){
        return temp;
    }
    
    
    //Diffuse Lighting
    Vector3D reflectRay = (dir.reflect()).hat();
    double product = reflectRay.dot(n);
    if (product > 0){
        r += color.red*product * material.kd;
        g += color.green*product * material.kd;
        b += color.blue*product * material.kd;
    }
    
    //Specular Lighting
    
    
    double epsilon = 10.0;
    Vector3D rVec(dir - (n*dir.dot(n)*2.0));
    double spec = rVec.dot(viewRay.d.reflect());
    double rw0e;
    if(spec > 0)
        rw0e = pow(spec,epsilon);
    else
        rw0e = 0;
    if(product > 0){
        r += color.red*rw0e * material.ks * 0.5;
        g += color.green*rw0e * material.ks * 0.5;
        b += color.blue*rw0e * material.ks * 0.5;
    }
    r = r*material.directScale;
    g = g*material.directScale;
    b = b*material.directScale;
    
    //Reflections
    double minTime = 100000.0;
    double tHitAnotherShape = 0.0;
    Vector3D recViewDir(viewRay.d - (2*viewRay.d*n)*n); //direction of mirror reflection
    recViewDir.normalize();
    
    Ray recViewRay(pt,recViewDir, "view");
    recViewRay.recurseLevel = viewRay.recurseLevel+1;
    Point3D recPt;
    RGBAPixel recColor;
    
    //Mirror Reflection
    if(material.reflectProperty == "mirror" && viewRay.recurseLevel < 3){
        
        GeometricObject* nextShape = NULL;
        
        for(int k = 0; k < shapes.size(); k++){
            if(shapes[k] == this)
                continue;
            
            tHitAnotherShape = shapes[k]->hit(recViewRay,recPt);
            if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                nextShape = shapes[k];
                minTime = tHitAnotherShape;
            }
        }
        if(nextShape != NULL){
            recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes);
            r += (recColor.red); //* (1-material.directScale);
            g += (recColor.green);// * (1-material.directScale);
            b += (recColor.blue);// * (1-material.directScale);
        }
    }
    if(material.reflectProperty == "glossy" && viewRay.recurseLevel < 3){
        
        double tempR = 0.0;
        double tempG = 0.0;
        double tempB = 0.0;
        
        Vector3D axisA = Vector3D(1,0,0).cross(recViewDir).hat() * 1;
        Vector3D axisB = axisA.cross(recViewDir).hat() * 1;

        Point3D tempPt = pt + recViewDir - 0.5*axisA - 0.5*axisB;
        Rectangle rect(tempPt, axisA, axisB);
        
        vector<Point3D> samplepts = rect.generatePoints(100);
        
        for(int i = 0; i < samplepts.size(); i++){
            Vector3D indirectDir(pt,samplepts[i]);
            Ray indirectRay(pt,indirectDir);
            indirectRay.recurseLevel = viewRay.recurseLevel + 1;
            
            GeometricObject* nextShape = NULL;
            double minTime = 100000.0;
            double tHitAnotherShape = 0.0;
            for(int k = 0; k < shapes.size(); k++){
                if(shapes[k] == this)
                    continue;
                
                tHitAnotherShape = shapes[k]->hit(indirectRay,recPt);
                if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                    nextShape = shapes[k];
                    minTime = tHitAnotherShape;
                }
                if(nextShape != NULL && nextShape->material.transparency == 0){
                    recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes);
                    tempR += (recColor.red);
                    tempG += (recColor.green);
                    tempB += (recColor.blue);
                }
            }
        }
        r += tempR / samplepts.size();
        g += tempG / samplepts.size();
        b += tempB / samplepts.size();
    }
    
    if(material.transparency > 0 && viewRay.recurseLevel == 0){
        double tempR = 255;
        double tempG = 255;
        double tempB = 255;
        
        Vector3D invNormal = n.reflect();
        Ray inverseRay(pt,invNormal);
        inverseRay.recurseLevel = viewRay.recurseLevel + 1;
        GeometricObject* nextShape = NULL;
        double minTime = 100000.0;
        double tHitAnotherShape = 0.0;
        for(int k = 0; k < shapes.size(); k++){
            if(shapes[k] == this)
                continue;
            
            tHitAnotherShape = shapes[k]->hit(inverseRay,recPt);
            if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                nextShape = shapes[k];
                minTime = tHitAnotherShape;
            }
            if(nextShape != NULL && nextShape != this){
                recColor = nextShape->rayTrace(lightSrc, recPt, inverseRay, shapes);
                tempR = (recColor.red);
                tempG = (recColor.green);
                tempB = (recColor.blue);
            }
        }
        r = tempR * material.transparency + (r*(1-material.transparency));
        g = tempG * material.transparency + (g*(1-material.transparency));
        b = tempB * material.transparency + (b*(1-material.transparency));
    }
    
    //cap off maximum color values
    r =std::min((int)r,255);
    g =std::min((int)g,255);
    b =std::min((int)b,255);
    
    temp(r,g,b);
    return temp;
}
예제 #2
0
NoDice::Font::
Font(const std::string& fontname, unsigned int pointsize)
: m_name(fontname)
, m_height(pointsize)
, m_glyph(s_max_char)
{
	// Calculate the maximum extent of textures supported by OpenGL.
	GLint max_tex_width;
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_width);

	FT_Library ftLib;
	FT_Error ftStatus = FT_Init_FreeType(&ftLib);
	if (ftStatus != 0)
	{
		throw std::runtime_error("error in FT_Init_Freetype");
	}

	FT_Face ftFace;
	ftStatus = FT_New_Face(ftLib, m_name.c_str(), 0, &ftFace);
	if (ftStatus != 0)
	{
		throw std::runtime_error("error in FT_New_Face");
	}

	// munge character size.  Freetype uses 1/64th of a point (1/4608 of an inch)
	// as its base unit, but the pointsize parameter of this function is in
	// points.  Conversion requires multiplying by 64, which is what the
	// shift-by-size operation does.
	//
	// I'm also assuming a screen pitch of 100 dots-per-inch.  This needs to be
	// adjusted to use autodetected or configurable values if possible.
	// @todo fix assumptions about screen dot pitch
	//
	int dpi = 100;
	ftStatus = FT_Set_Char_Size(ftFace, pointsize<<6, pointsize<<6, dpi, dpi);

	// Import the bitmap for each character in the font.  This go-round, we're
	// only supportin 7-bit ASCII.
	// @todo fix assumptions about character sets
	GLsizei curTexWidth = 0;
	GLsizei maxTexWidth = 0;
	GLsizei curTexHeight = 0;
	GLsizei maxTexHeight = 0;
	int    glyphCount = 0;
	for (unsigned char c = 0; c < s_max_char; ++c)
	{
		ftStatus = FT_Load_Char(ftFace, c, FT_LOAD_RENDER);
		if (ftStatus != 0)
		{
			throw std::runtime_error("error in FT_Load_Glyph");
		}

		m_glyph[c].left      = ftFace->glyph->bitmap_left;
		m_glyph[c].top       = ftFace->glyph->bitmap_top;
		m_glyph[c].width     = ftFace->glyph->bitmap.width;
		m_glyph[c].height    = ftFace->glyph->bitmap.rows;
		m_glyph[c].advance   = ftFace->glyph->advance.x >> 6;

		// If this glyph fits in current line, add to totals otherwise start a new
		// line.
		if (curTexWidth + m_glyph[c].width < max_tex_width)
		{
			curTexWidth += m_glyph[c].width;
			curTexHeight = std::max(curTexHeight, m_glyph[c].height);
			++glyphCount;
		}
		else
		{
			maxTexWidth = std::max(maxTexWidth, curTexWidth);
			curTexWidth = m_glyph[c].width;
			maxTexHeight += std::max(curTexHeight, m_glyph[c].height);
			curTexHeight = 0;
			glyphCount = 0;
		}

		// Allocate the required memory for this glyph's bitmap.
		//
		// The bitmap needs width*height bytes for the luminance component
		// and the same again for the glyph's alpha component.
		m_glyph[c].bitmap = Glyph::Bitmap(m_glyph[c].width
		                                  * m_glyph[c].height
		                                  * 2*sizeof(GLubyte));

		// Convert the freefont bitmap into an opengl GL_LUMINANCE_ALPHA bitmap by
		// setting the alpha to 255 (0xff) wherever the luminance is greater than
		// zero.  See, a lot of truetype fonts have built-in antialiasing.  This
		// mechanism trats a zero luminance as a transparent background.
		int i = 0;
		for (int y = 0; y < m_glyph[c].height; ++y)
		{
			for (int x = 0; x < m_glyph[c].width; ++x)
			{
				int index = x + m_glyph[c].width*y;
				m_glyph[c].bitmap[i++] = ftFace->glyph->bitmap.buffer[index];
				m_glyph[c].bitmap[i++] = (ftFace->glyph->bitmap.buffer[index] > 0 ? 0xff : 0);
			}
		}
	}

	FT_Done_Face(ftFace);
	FT_Done_FreeType(ftLib);

	maxTexWidth = std::max(maxTexWidth, curTexWidth);
	maxTexHeight += curTexHeight;
	m_textureWidth  = nextPowerOfTwo(maxTexWidth);
	m_textureHeight = nextPowerOfTwo(maxTexHeight);
	mapToTexture();
}