コード例 #1
0
ファイル: PsychGLGlue.c プロジェクト: BR-Innes/Psychtoolbox-3
/*
    PsychSetGLColor()
    
    Accept a Psych color structure and a depth value and call the appropriate variant of glColor.       
*/
void PsychSetGLColor(PsychColorType *color, PsychWindowRecordType *windowRecord)
{
    int numVals;
    
    numVals=PsychConvertColorToDoubleVector(color, windowRecord, (GLdouble*) &(windowRecord->currentColor));
    if(numVals < 3 || numVals > 4) PsychErrorExitMsg(PsychError_internal, "Palette mode not yet implemented or illegal color specifier.");

	// Set the color in GL:
	if (windowRecord->defaultDrawShader) {
		// Drawshader color submission:
		HDRglColor4dv(windowRecord->currentColor);
	}
	else {
		// Fixed function pipe:
        if (PsychIsGLClassic(windowRecord)) {
            // OpenGL-1/2:
            glColor4dv(windowRecord->currentColor);
        }
        else {
            // OpenGL-ES 1.x: glColor4f() is only available function.
            glColor4f((float) windowRecord->currentColor[0], (float) windowRecord->currentColor[1], (float) windowRecord->currentColor[2], (float) windowRecord->currentColor[3]);
            PsychGLColor4f(windowRecord, (float) windowRecord->currentColor[0], (float) windowRecord->currentColor[1], (float) windowRecord->currentColor[2], (float) windowRecord->currentColor[3]);
        }
	}
}
コード例 #2
0
PsychError SCREENDrawTexture(void) 
{
static char synopsisString[] = 
	"Draw the texture specified via 'texturePointer' into the target window specified via 'windowPointer'. "
	"In the the OS X Psychtoolbox textures replace offscreen windows for fast drawing of images during animation."
	"'sourceRect' specifies a rectangular subpart of the texture to be drawn (Defaults to full texture). "
	"'destinationRect' defines the rectangular subpart of the window where the texture should be drawn. This defaults"
	"to centered on the screen. "
	"'rotationAngle' Specifies a rotation angle in degree for rotated drawing of the texture (Defaults to 0 deg. = upright). "
	"'filterMode' How to compute the pixel color values when the texture is drawn magnified, minified or drawn shifted, e.g., "
	"if sourceRect and destinationRect do not have the same size or if sourceRect specifies fractional pixel values. 0 = Nearest "
	"neighbour filtering, 1 = Bilinear filtering - this is the default. Values 2 or 3 select use of OpenGL mip-mapping for improved "
    "quality: 2 = Bilinear filtering for nearest mipmap level, 3 = Trilinear filtering across mipmap levels, 4 = Nearest neighbour "
    "filtering for nearest mipmap level, 5 = nearest neighbour filtering with linear interpolation between mipmap levels. Mipmap filtering is "
    "only supported for GL_TEXTURE_2D textures (see description of 'specialFlags' flag 1 below). A negative filterMode value will "
    "also use mip-mapping for fast drawing of blurred textures if the GL_TEXTURE_2D format is used: Mip-maps are essentially image "
    "resolution pyramids, the filterMode value selects a specific layer in that pyramid. A value of -1 draws the highest resolution "
    "layer, a value of -2 draws a half-resolution layer, a value of -3 draws a quarter resolution layer and so on. Each layer has "
    "half the resolution of the preceeding layer. This allows for very fast drawing of blurred or low-pass filtered images, e.g., for "
    "gaze-contingent displays. However, the filter function for downsampling is system dependent and may vary across graphics cards, "
    "although a box-filter is the most common type. If you need a well defined filter function, use a custom written GLSL shader "
    "instead, so you have full control over the mathematical properties of the downsampling function. This would incur a "
    "performance penalty.\n"
    "'globalAlpha' A global alpha transparency value to apply "
	"to the whole texture for blending. Range is 0 = fully transparent to 1 = fully opaque, defaults to one. If both, an alpha-channel "
	"and globalAlpha are provided, then the final alpha is the product of both values. 'modulateColor', if provided, overrides the "
	"'globalAlpha' value. If 'modulateColor' is specified, the 'globalAlpha' value will be ignored. 'modulateColor' will be a global "
	"color that gets applied to the texture as a whole, i.e., it modulates each color channel. E.g., modulateColor = [128 255 0] would "
	"leave the green- and alpha-channel untouched, but it would multiply the blue channel with 0 - set it to zero blue intensity, and "
	"it would multiply each texel in the red channel by 128/255 - reduce its intensity to 50%. The most interesting application of "
	"'modulateColor' is drawing of arbitrary complex shapes of selectable color: Simply generate an all-white luminance texture of "
	"arbitrary shape, possibly with alpha channel, then draw it with 'modulateColor' set to the wanted color and global alpha value.\n"
	"'textureShader' (optional): If you provide a valid handle of a GLSL shader, this shader will be applied to the texture during "
	"drawing. If the texture already has a shader assigned (via Screen('MakeTexture') or automatically by PTB for some reason), then "
	"the shader provided here as 'textureShader' will silently override the shader assigned earlier. Application of shaders this way "
	"is mostly useful for application of simple single-pass image processing operations to a texture, e.g., a simple blur or a "
	"deinterlacing operation for a video texture. If you intend to use this texture multiple times or if you need more complex image "
	"processing, e.g., multi-pass operations, better use the Screen('TransformTexture') command. It allows for complex operations to "
	"be applied and is more flexible.\n"
	"'specialFlags' optional argument: Allows to pass a couple of special flags to influence the drawing. The flags can be combined "
	"by mor() ing them together. A value of kPsychUseTextureMatrixForRotation will use a different mode of operation for drawing of "
	"rotated textures, where the drawn 'dstRect' texture rectangle is always upright, but texels are retrieved at rotated positions, "
	"as if the 'srcRect' rectangle would be rotated. If you set a value of kPsychDontDoRotation then the rotation angle will not be "
	"used to rotate the texture. Instead it will be passed to a bount texture shader (if any), which is free to interpret the "
	"'rotationAngle' parameters is it wants - e.g., to implement custom texture rotation."
	"\n\n"
	"'auxParameters' optional argument: If this is set as a vector with at least 4 components, and a multiple of four components, "
	"then these values are passed to a shader (if any is bound) as 'auxParameter0....n'. The current implementation supports at "
	"most 32 values per draw call. This is mostly useful when drawing procedural textures if one needs to pass more additional "
	"parameters to define the texture than can fit into other parameter fields. See 'help ProceduralShadingAPI' for more info. "
	"\n\n"
	"If you want to draw many textures to the same onscreen- or offscreen window, use the function Screen('DrawTextures'). "
	"It accepts the same arguments as this function, but is optimized to draw many textures in one call.";
	
	// If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
	static char useString[] = "Screen('DrawTexture', windowPointer, texturePointer [,sourceRect] [,destinationRect] [,rotationAngle] [, filterMode] [, globalAlpha] [, modulateColor] [, textureShader] [, specialFlags] [, auxParameters]);";
	//                                               1              2                3             4                5                6              7				8					9				10				 11

	PsychWindowRecordType		*source, *target;
	PsychRectType			sourceRect, targetRect, tempRect;
	double rotationAngle = 0;   // Default rotation angle is zero deg. = upright.
	int filterMode = 1;         // Default filter mode is bilinear filtering.
	double globalAlpha = 1.0;   // Default global alpha is 1 == no effect.
	PsychColorType	color;
	int textureShader, backupShader;
	double*							auxParameters;
	int								numAuxParams, m, n, p;
    psych_bool isclassic;
	int specialFlags = 0;

    //all subfunctions should have these two lines.  
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
    
    //Get the window structure for the onscreen window.  It holds the onscreein GL context which we will need in the
    //final step when we copy the texture from system RAM onto the screen.
    PsychErrorExit(PsychCapNumInputArgs(11));   	
    PsychErrorExit(PsychRequireNumInputArgs(2)); 	
    PsychErrorExit(PsychCapNumOutputArgs(0)); 
	
    //Read in arguments
    PsychAllocInWindowRecordArg(1, kPsychArgRequired, &target);
    PsychAllocInWindowRecordArg(2, kPsychArgRequired, &source);
    if(source->windowType!=kPsychTexture) {
      PsychErrorExitMsg(PsychError_user, "The first argument supplied was a window pointer, not a texture pointer");
    }

    // Classic OpenGL-1/2?
    isclassic = PsychIsGLClassic(target);

    PsychCopyRect(sourceRect,source->clientrect);
    PsychCopyInRectArg(3, kPsychArgOptional, sourceRect);
    if (IsPsychRectEmpty(sourceRect)) return(PsychError_none);

    PsychCopyRect(tempRect, target->clientrect);    
    PsychCenterRectInRect(sourceRect, tempRect, targetRect);
    PsychCopyInRectArg(4, kPsychArgOptional, targetRect);
    if (IsPsychRectEmpty(targetRect)) return(PsychError_none);

    PsychCopyInDoubleArg(5, kPsychArgOptional, &rotationAngle);
    PsychCopyInIntegerArg(6, kPsychArgOptional, &filterMode);
    if (filterMode > 5) {
        PsychErrorExitMsg(PsychError_user, "filterMode needs to be negative for a specific blur level, or at most 5 for other modes.");    
    }

	// Copy in optional 'globalAlpha': We don't put restrictions on its valid range
	// anymore - That made sense for pure fixed function LDR rendering, but no longer
	// for HDR rendering or procedural shading.
    PsychCopyInDoubleArg(7, kPsychArgOptional, &globalAlpha);
    
    PsychSetDrawingTarget(target);
    PsychUpdateAlphaBlendingFactorLazily(target);
	
	if(PsychCopyInColorArg(8, kPsychArgOptional, &color)) {
		// set globalAlpha to DBL_MAX to signal that PsychBlitTexture() shouldn't
		// use this parameter and not set any modulate color, cause we do it.
		globalAlpha = DBL_MAX;
		
		// Setup global vertex color as modulate color for texture drawing:
		PsychCoerceColorMode(&color);

		// This call stores unclamped color in target->currentColor, as needed
		// if color is to be processed by some bound shader (procedural or filtershader)
		// inside PsychBlitTextureToDisplay():
		PsychConvertColorToDoubleVector(&color, target, (GLdouble*) &(target->currentColor));

		// Submit the same color to fixed function pipe attribute as well, in case no
		// shader is bound, or shader pulls from standard color attribute (we can't know yet):
        if (isclassic) {
            glColor4dv(target->currentColor);
        }
        else {
            PsychGLColor4f(target, (float) target->currentColor[0], (float) target->currentColor[1], (float) target->currentColor[2], (float) target->currentColor[3]);
        }
	}

	// Assign optional override texture shader, if any provided:
	textureShader = -1;
    PsychCopyInIntegerArg(9, kPsychArgOptional, &textureShader);

	// Assign any other optional special flags:
    PsychCopyInIntegerArg(10, kPsychArgOptional, &specialFlags);
	
	// Set rotation mode flag for texture matrix rotation if secialFlags is set accordingly:
	if (specialFlags & kPsychUseTextureMatrixForRotation) source->specialflags|=kPsychUseTextureMatrixForRotation;
	// Set rotation mode flag for no fixed function pipeline rotation if secialFlags is set accordingly:
	if (specialFlags & kPsychDontDoRotation) source->specialflags|=kPsychDontDoRotation;

	// Optional auxParameters:
	auxParameters = NULL;
	m=n=p=0;
	if (PsychAllocInDoubleMatArg(11, kPsychArgOptional, &m, &n, &p, &auxParameters)) {
		if ((p!=1) || (m * n < 4) || (((m*n) % 4)!=0)) PsychErrorExitMsg(PsychError_user, "The 11th argument must be a vector of 'auxParameter' values with a multiple of 4 components.");
	}
	numAuxParams = m*n;
	target->auxShaderParamsCount = numAuxParams;

	// Pass auxParameters for current primitive in the auxShaderParams field.
	if (numAuxParams > 0) {
		target->auxShaderParams = auxParameters;
	}
	else {
		target->auxShaderParams = NULL;
	}
	
	if (textureShader > -1) {
		backupShader = source->textureFilterShader;
		source->textureFilterShader = -1 * textureShader;
		PsychBlitTextureToDisplay(source, target, sourceRect, targetRect, rotationAngle, filterMode, globalAlpha);	
		source->textureFilterShader = backupShader;
	}
	else {
		PsychBlitTextureToDisplay(source, target, sourceRect, targetRect, rotationAngle, filterMode, globalAlpha);	
	}
	
	// Reset rotation mode flag:
	source->specialflags &= ~(kPsychUseTextureMatrixForRotation | kPsychDontDoRotation);
	
	target->auxShaderParams = NULL;
	target->auxShaderParamsCount = 0;
	
    // Mark end of drawing op. This is needed for single buffered drawing:
    PsychFlushGL(target);

    return(PsychError_none);

}