Exemple #1
0
bool OpenGLFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLFrameBuffer *fb)
{
	bool done;

	BurnTime += ticks;
	ticks *= 2;

	// Make the fire burn
	done = false;
	while (!done && ticks--)
	{
		Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
		done = (Density < 0);
	}

	if (BurnTexture != NULL) delete BurnTexture;
	BurnTexture = new GLTexture(WIDTH, HEIGHT, false, false);

	// Update the burn texture with the new burn data
	BYTE rgb_buffer[WIDTH*HEIGHT*4];

	const BYTE *src = BurnArray;
	DWORD *dest = (DWORD *)rgb_buffer;
	for (int y = HEIGHT; y != 0; --y)
	{
		for (int x = WIDTH; x != 0; --x)
		{
			BYTE s = clamp<int>((*src++)*2, 0, 255);
			*dest++ = MAKEARGB(s,255,255,255);
		}
	}

	// Put the initial screen back to the buffer.
	gl_SetTextureMode(TM_OPAQUE);
	gl.Disable(GL_ALPHA_TEST);
	fb->wipestartscreen->Bind(0, CM_DEFAULT);
	gl.Color4f(1.f, 1.f, 1.f, 1.f);
	gl.Begin(GL_TRIANGLE_STRIP);
	gl.TexCoord2f(0, fb->wipestartscreen->GetVB());
	gl.Vertex2i(0, 0);
	gl.TexCoord2f(0, 0);
	gl.Vertex2i(0, fb->Height);
	gl.TexCoord2f(fb->wipestartscreen->GetUR(), fb->wipestartscreen->GetVB());
	gl.Vertex2i(fb->Width, 0);
	gl.TexCoord2f(fb->wipestartscreen->GetUR(), 0);
	gl.Vertex2i(fb->Width, fb->Height);
	gl.End();

	gl_SetTextureMode(TM_MODULATE);
	gl.ActiveTexture(GL_TEXTURE1);
	gl.Enable(GL_TEXTURE_2D);

	// mask out the alpha channel of the wipeendscreen.
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE1);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); 
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);

	gl.ActiveTexture(GL_TEXTURE0);

	// Burn the new screen on top of it.
	gl.Color4f(1.f, 1.f, 1.f, 1.f);
	fb->wipeendscreen->Bind(1, CM_DEFAULT);
	//BurnTexture->Bind(0, CM_DEFAULT);

	BurnTexture->CreateTexture(rgb_buffer, WIDTH, HEIGHT, false, 0, CM_DEFAULT);
	gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


	gl.Begin(GL_TRIANGLE_STRIP);
	gl.MultiTexCoord2f(GL_TEXTURE0, 0, 0);
	gl.MultiTexCoord2f(GL_TEXTURE1, 0, fb->wipestartscreen->GetVB());
	gl.Vertex2i(0, 0);
	gl.MultiTexCoord2f(GL_TEXTURE0, 0, BurnTexture->GetVB());
	gl.MultiTexCoord2f(GL_TEXTURE1, 0, 0);
	gl.Vertex2i(0, fb->Height);
	gl.MultiTexCoord2f(GL_TEXTURE0, BurnTexture->GetUR(), 0);
	gl.MultiTexCoord2f(GL_TEXTURE1, fb->wipestartscreen->GetUR(), fb->wipestartscreen->GetVB());
	gl.Vertex2i(fb->Width, 0);
	gl.MultiTexCoord2f(GL_TEXTURE0, BurnTexture->GetUR(), BurnTexture->GetVB());
	gl.MultiTexCoord2f(GL_TEXTURE1, fb->wipestartscreen->GetUR(), 0);
	gl.Vertex2i(fb->Width, fb->Height);
	gl.End();

	gl.ActiveTexture(GL_TEXTURE1);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	gl.Disable(GL_TEXTURE_2D);
	gl.ActiveTexture(GL_TEXTURE0);

	// The fire may not always stabilize, so the wipe is forced to end
	// after an arbitrary maximum time.
	return done || (BurnTime > 40);
}
bool OpenGLSWFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLSWFrameBuffer *fb)
{
	bool done;

	BurnTime += ticks;
	ticks *= 2;

	// Make the fire burn
	done = false;
	while (!done && ticks--)
	{
		Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
		done = (Density < 0);
	}

	// Update the burn texture with the new burn data

	if (BurnTexture->Buffers[0] == 0)
	{
		glGenBuffers(2, (GLuint*)BurnTexture->Buffers);
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, BurnTexture->Buffers[0]);
		glBufferData(GL_PIXEL_UNPACK_BUFFER, WIDTH * HEIGHT, nullptr, GL_STREAM_DRAW);
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, BurnTexture->Buffers[1]);
		glBufferData(GL_PIXEL_UNPACK_BUFFER, WIDTH * HEIGHT, nullptr, GL_STREAM_DRAW);
	}
	else
	{
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, BurnTexture->Buffers[BurnTexture->CurrentBuffer]);
		BurnTexture->CurrentBuffer = (BurnTexture->CurrentBuffer + 1) & 1;
	}

	uint8_t *dest = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, WIDTH * HEIGHT, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
	if (dest)
	{
		memcpy(dest, BurnArray, WIDTH * HEIGHT);
		glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

		GLint oldBinding = 0;
		glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
		glBindTexture(GL_TEXTURE_2D, BurnTexture->Texture);
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RED, GL_UNSIGNED_BYTE, 0);
		glBindTexture(GL_TEXTURE_2D, oldBinding);

		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
	}

	// Put the initial screen back to the buffer.
	DrawScreen(fb, fb->InitialWipeScreen);

	// Burn the new screen on top of it.
	float right = float(fb->Width);
	float bot = float(fb->Height);

	BURNVERTEX verts[4] =
	{
		{ 0.f,   0.f, 0.f, 1.f, 0.f, 0.f, 0, 0 },
		{ right, 0.f, 0.f, 1.f, 1.f, 0.f, 1, 0 },
		{ right, bot, 0.f, 1.f, 1.f, 1.f, 1, 1 },
		{ 0.f,   bot, 0.f, 1.f, 0.f, 1.f, 0, 1 }
	};

	fb->SetTexture(0, fb->FinalWipeScreen);
	fb->SetTexture(1, BurnTexture);
	fb->SetAlphaBlend(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	fb->SetPixelShader(fb->Shaders[SHADER_BurnWipe]);
	glActiveTexture(GL_TEXTURE1);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	fb->DrawTriangleFans(2, verts);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glActiveTexture(GL_TEXTURE0);

	// The fire may not always stabilize, so the wipe is forced to end
	// after an arbitrary maximum time.
	return done || (BurnTime > 40);
}
bool OpenGLFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLFrameBuffer *fb)
{
    bool done;

    BurnTime += ticks;
    ticks *= 2;

    // Make the fire burn
    done = false;
    while (!done && ticks--)
    {
        Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
        done = (Density < 0);
    }

    if (BurnTexture != NULL) delete BurnTexture;
    BurnTexture = new FHardwareTexture(WIDTH, HEIGHT, true);

    // Update the burn texture with the new burn data
    BYTE rgb_buffer[WIDTH*HEIGHT*4];

    const BYTE *src = BurnArray;
    DWORD *dest = (DWORD *)rgb_buffer;
    for (int y = HEIGHT; y != 0; --y)
    {
        for (int x = WIDTH; x != 0; --x)
        {
            BYTE s = clamp<int>((*src++)*2, 0, 255);
            *dest++ = MAKEARGB(s,255,255,255);
        }
    }

    float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth());
    float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight());


    // Put the initial screen back to the buffer.
    gl_RenderState.SetTextureMode(TM_OPAQUE);
    gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
    gl_RenderState.ResetColor();
    gl_RenderState.Apply();
    fb->wipestartscreen->Bind(0, 0, false);
    FFlatVertex *ptr;
    unsigned int offset, count;
    ptr = GLRenderer->mVBO->GetBuffer();
    ptr->Set(0, 0, 0, 0, vb);
    ptr++;
    ptr->Set(0, fb->Height, 0, 0, 0);
    ptr++;
    ptr->Set(fb->Width, 0, 0, ur, vb);
    ptr++;
    ptr->Set(fb->Width, fb->Height, 0, ur, 0);
    ptr++;
    GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP, &offset, &count);

    gl_RenderState.SetTextureMode(TM_MODULATE);
    gl_RenderState.SetEffect(EFF_BURN);
    gl_RenderState.ResetColor();
    gl_RenderState.Apply();

    // Burn the new screen on top of it.
    fb->wipeendscreen->Bind(0, 0, false);

    BurnTexture->CreateTexture(rgb_buffer, WIDTH, HEIGHT, 1, true, 0);

    GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, offset, count);
    gl_RenderState.SetEffect(EFF_NONE);

    // The fire may not always stabilize, so the wipe is forced to end
    // after an arbitrary maximum time.
    return done || (BurnTime > 40);
}
Exemple #4
0
bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb)
{
	bool done;

	BurnTime += ticks;
	ticks *= 2;

	// Make the fire burn
	done = false;
	while (!done && ticks--)
	{
		Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
		done = (Density < 0);
	}

	// Update the burn texture with the new burn data
	D3DLOCKED_RECT lrect;
	if (SUCCEEDED(BurnTexture->LockRect(0, &lrect, NULL, D3DLOCK_DISCARD)))
	{
		const BYTE *src = BurnArray;
		BYTE *dest = (BYTE *)lrect.pBits;
		for (int y = HEIGHT; y != 0; --y)
		{
			for (int x = WIDTH; x != 0; --x)
			{
				*dest++ = *src++;
			}
			dest += lrect.Pitch - WIDTH;
		}
		BurnTexture->UnlockRect(0);
	}

	// Put the initial screen back to the buffer.
	IDirect3DSurface9 *source = NULL, *target;

	if (SUCCEEDED(fb->InitialWipeScreen->GetSurfaceLevel(0, &source)) &&
		SUCCEEDED(fb->D3DDevice->GetRenderTarget(0, &target)))
	{
		fb->D3DDevice->UpdateSurface(source, NULL, target, NULL);
		target->Release();
	}
	if (source != NULL)
	{
		source->Release();
	}

	// Burn the new screen on top of it.
	float top = fb->LBOffset - 0.5f;
	float right = float(fb->Width) - 0.5f;
	float bot = float(fb->Height) + top;
	float texright = float(fb->Width) / float(fb->FBWidth);
	float texbot = float(fb->Height) / float(fb->FBHeight);

	BURNVERTEX verts[4] =
	{
		{ -0.5f, top, 0.5f, 1.f,      0.f,    0.f, 0, 0 },
		{ right, top, 0.5f, 1.f, texright,    0.f, 1, 0 },
		{ right, bot, 0.5f, 1.f, texright, texbot, 1, 1 },
		{ -0.5f, bot, 0.5f, 1.f,      0.f, texbot, 0, 1 }
	};

	fb->D3DDevice->SetFVF(D3DFVF_BURNVERTEX);
	fb->SetTexture(0, fb->FinalWipeScreen);
	fb->SetTexture(1, BurnTexture);
	fb->SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
	fb->SetPixelShader(fb->BurnShader);
	fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	if (fb->SM14)
	{
		fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
		fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
	}
	fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(BURNVERTEX));
	fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
	if (fb->SM14)
	{
		fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
		fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
	}
	fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);

	// The fire may not always stabilize, so the wipe is forced to end
	// after an arbitrary maximum time.
	return done || (BurnTime > 40);
}