本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制

  这里先看下最终效果:

                    

这里分别实现了灰度效果及残影的效果。

一、绘制基类

  这里主要参考了cocos2dx源码中 RenderTexture 的实现,有兴趣的可以了解下。

绘制基类RenderShader主要实现以下方法:

//******************************************************************
// 文件名: RenderShader.h
// 创建人: 稀饭lei
// 版 本: 1.0
// 描 述: 特效基类
//******************************************************************
#ifndef _RenderShader_H__
#define _RenderShader_H__
#include "cocos2d.h"
USING_NS_CC; // GL纹理坐标组
static const GLfloat ccRenderTextcord[] ={
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
class RenderShader : public Node
{
public:
static RenderShader* create(); virtual bool LoadByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray); //加载 shader文件 void begin(); // 用于设置绘制开始要调用的onBegin void end(); // 用于设置绘制结束要调用的onEnd void push2Draw(Node* node); // 添加待绘制节点 virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override; // cocos2dx绘制回调 protected:
virtual void onBegin(); virtual void onEnd(); //virtual void onClear(); virtual void Render(); // 绘制实现 virtual bool init(); virtual void CreateFrameBuffer(); //创建FBO及texture RenderShader(void); virtual ~RenderShader(void); GLuint m_nFrameBuffer; // 用于当前绘制的fbo GLuint m_nFrameBufferTexture; // 用于绑定在fbo中的texture GLProgram* m_glprogram; // GL绘制管理 GLint m_nOldFBO; // 原来的fbo CustomCommand _beginCommand;
CustomCommand _endCommand;
GroupCommand _groupCommand; std::set<Node*> sRenderChild; // 需要绘制的节点 Size m_sRenderSize;
}; #endif

这里有几个主要实现:

1、我们用push2Draw(Node* node);  方法将待绘制的节点添加到sRenderChild中等待处理。

2、参考RenderTexture 的实现,我们也利用begin,end将需要绘制的节点利用visit访问添加到当前的RenderShader类所在的render层中进行绘制。

3、在实际绘制过程中调用的onBegin中缓存对应的坐标系,同时绑定我们创建的FBO使得visit进来的节点可以绘制到当前FBO中。然后在onEnd中调用render方法将我们的FBO内容绘制原来cocos2dx底层的FBO上。

4、在render()实现如何绘制当前FBO的内容到cocos2dx的FBO上。(实际shader作业的地方)

详细实现代码如下:

#include "RenderShader.h"
#define STRINGIFY(A) #A
const char* ccPositionTextureColor_frag_test = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n varying vec4 v_fragmentColor;
varying vec2 v_texCoord; void main()
{
vec4 color = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(vec3(gray), color.a);
}
); RenderShader* RenderShader::create()
{
auto node = new RenderShader();
if (node && node->init())
{
node->autorelease();
return node;
}
delete node;
return nullptr;
} bool RenderShader::init()
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
} CreateFrameBuffer(); m_glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, ccPositionTextureColor_frag_test);
m_glprogram->retain(); return true;
} RenderShader::RenderShader(void)
:m_nFrameBuffer(), m_nFrameBufferTexture(), m_glprogram(nullptr)
{
GLView* glView = Director::getInstance()->getOpenGLView();
if (!glView)
{
return;
}
//屏幕大小
m_sRenderSize = glView->getFrameSize();
} RenderShader::~RenderShader(void)
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
}
if (m_nFrameBuffer)
{
glDeleteFramebuffers(, &m_nFrameBuffer);
m_nFrameBuffer = ;
}
if (m_nFrameBufferTexture)
{
glDeleteTextures(, &m_nFrameBufferTexture);
m_nFrameBufferTexture = ;
}
} bool RenderShader::LoadByteArray(const GLchar* vShaderByteArray, const GLchar* fShaderByteArray)
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
} this->CreateFrameBuffer(); m_glprogram = GLProgram::createWithByteArrays(vShaderByteArray, fShaderByteArray);
m_glprogram->retain(); return true;
} void RenderShader::onBegin()
{
if (!m_nFrameBuffer)
{
return;
}
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); //save old fbo and bind own
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
} void RenderShader::onEnd()
{
if (!m_nFrameBuffer)
{
return;
} // restore viewport for render to direct fbo
Director *director = Director::getInstance();
// restore viewport
director->setViewport();
this->Render(); glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
} void RenderShader::Render()
{
if (!m_glprogram || !m_nFrameBufferTexture)
{
return;
} glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
m_glprogram->use();
m_glprogram->setUniformsForBuiltins(); //GLuint glTexture = m_glprogram->getUniformLocationForName("CC_Texture0");
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, m_nFrameBufferTexture);
//glUniform1i(glTexture, 0);
GL::bindTexture2D(m_nFrameBufferTexture);
Size sSize = Director::getInstance()->getVisibleSize();
float x = ;
float y = ;
float w = sSize.width;
float h = sSize.height;
GLfloat vertices[] = {
x, y + h,
x + w, y + h,
x, y,
x + w, y
}; glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, , GL_FLOAT, GL_FALSE, , ccRenderTextcord); glDrawArrays(GL_TRIANGLE_STRIP, , ); /*GL::bindVAO(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);*/
} void RenderShader::CreateFrameBuffer()
{
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
if (m_nFrameBuffer == )
{
glGenFramebuffers(, &m_nFrameBuffer); if (m_nFrameBuffer == )
{
CCLOG("m_FilterFrameBuffer == 0");
return;
}
}
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer); if (m_nFrameBufferTexture == )
{
glGenTextures(, &m_nFrameBufferTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_nFrameBufferTexture); GLsizei nWidth = m_sRenderSize.width;
GLsizei nHeight = m_sRenderSize.height;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, nWidth, nHeight, , GL_RGBA, GL_UNSIGNED_BYTE, );
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
CCLOG("cocos2d: Texture2D: Error uploading compressed texture glError: 0x%04X", err);
return;
} }
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_nFrameBufferTexture, ); GLenum error;
if ((error = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)
{
CCLOG("Failed to make complete framebuffer object 0x%X", error);
return;
} glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
} void RenderShader::begin()
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); _groupCommand.init(_globalZOrder); Renderer *renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID()); _beginCommand.init(_globalZOrder);
_beginCommand.func = CC_CALLBACK_0(RenderShader::onBegin, this); renderer->addCommand(&_beginCommand);
} void RenderShader::end()
{
_endCommand.init(_globalZOrder);
_endCommand.func = CC_CALLBACK_0(RenderShader::onEnd, this); Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack"); Renderer *renderer = director->getRenderer();
renderer->addCommand(&_endCommand);
renderer->popGroup(); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } void RenderShader::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
//Begin will create a render group using new render target
begin(); ////clear screen
//_clearCommand.init(_globalZOrder);
//_clearCommand.func = CC_CALLBACK_0(RenderShader::onClear, this);
//renderer->addCommand(&_clearCommand); //! make sure all children are drawn
{
auto it = sRenderChild.begin();
while (it != sRenderChild.end())
{
if (Node* node = *it)
{
node->visit(renderer, transform, flags);
node->release();
}
++it;
}
sRenderChild.clear();
}
//End will pop the current render group
end();
} void RenderShader::push2Draw(Node* node)
{
if (node && sRenderChild.find(node) == sRenderChild.end())
{
node->retain();
sRenderChild.insert(node);
}
else
{
CCLOG(" push same!!!");
}
}

这里shader代码实现的是灰度图的效果,其他效果可以自己修改ccPositionTextureColor_frag_test内容。

二、实际使用

1、将RenderShader当成正常的Node使用,设置父节点及index坐标等。

        m_pShader = RenderShader::create();
this->addChild(m_pShader);

2、因为RenderShader在draw中对需要绘制的子节点进行了清理,所以需要每次重新对子节点进行添加,添加动画节点如下:

void CPlayer::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
if (m_pShader)
{
m_pShader->push2Draw(m_pNode);
}
}

主要事项:RenderShader在Render方法中将内容绘制到原来的FBO中,而cocos2dx对每个需要绘制的同一index层级会在开始的时候单独创建一个FBO来处理。因而如果RenderShader单独一个层级可能导致此时的FBO没有创建,导致没有绘制效果。

到这里我们就实现灰色角色的效果了,使用也依照cocos2dx的用法,相对简单。

三、残影效果扩展

主要实现代码如下:

//******************************************************************
// 文件名: RemindShader.h
// 创建人: 稀饭lei
// 版 本: 1.0
// 描 述: 残影特效
//******************************************************************
#ifndef _RemindShader_H__
#define _RemindShader_H__
#include "RenderShader.h"
USING_NS_CC;
#define REMIND_RENDER_COUNT 5 // 残影个数
class RemindShader :public RenderShader
{
public:
static RemindShader* create(); virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
private:
virtual void onBegin() override; //virtual void onClear(); virtual void Render() override; virtual bool init() override; virtual void CreateFrameBuffer() override; RemindShader(void); virtual ~RemindShader(void); GLuint m_pTextureArr[REMIND_RENDER_COUNT]; int m_nRenderFrq; // 渲染间隔帧率 int m_nRenderCount; // 渲染间隔计数 int m_nCurTexutreIndex; // 当前渲染的纹理ID
}; #endif #include "RemindShader.h" #define STRINGIFY(A) #A
const char* ccRemind_fsh = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n varying vec2 v_texCoord;
uniform float u_alpha; void main()
{
vec4 pcolor = texture2D(CC_Texture0, v_texCoord) * u_alpha;
gl_FragColor = pcolor;
}
); RemindShader* RemindShader::create()
{
auto node = new RemindShader();
if (node && node->init())
{
node->autorelease();
return node;
}
delete node;
return nullptr;
} bool RemindShader::init()
{
if (m_glprogram)
{
m_glprogram->release();
m_glprogram = nullptr;
} CreateFrameBuffer();
m_glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, ccRemind_fsh);
m_glprogram->retain();
return true;
} RemindShader::RemindShader(void)
: m_nCurTexutreIndex(), m_nRenderFrq(), m_nRenderCount()
{
memset(m_pTextureArr, , REMIND_RENDER_COUNT);
} RemindShader::~RemindShader(void)
{
if (m_pTextureArr[])
{
glDeleteTextures(REMIND_RENDER_COUNT, m_pTextureArr);
memset(m_pTextureArr, , REMIND_RENDER_COUNT);
}
} void RemindShader::onBegin()
{
if (!m_nFrameBuffer)
{
return;
}
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
// director->setProjection(director->getProjection());
// GLView* glView = director->getOpenGLView();
// if (!glView)
// {
// return;
// }
// Size frameSize =glView->getFrameSize();
// {
// // Calculate the adjustment ratios based on the old and new projections
// Size size = director->getWinSizeInPixels();
// float widthRatio = size.width / frameSize.width;
// float heightRatio = size.height / frameSize.height;
// //caculate the projections of size change
// Mat4 orthoMatrix;
// Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix);
// director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
// }
//
// //calculate viewport
// {
// glViewport(0, 0, (GLsizei)(frameSize.width), (GLsizei)(frameSize.height));
// }
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
// 仅在计数为0才更新新的渲染
if (m_nRenderCount == )
{
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureArr[m_nCurTexutreIndex], );
m_nCurTexutreIndex = m_nCurTexutreIndex + < REMIND_RENDER_COUNT ? m_nCurTexutreIndex + : ; glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
} void RemindShader::Render()
{
if (!m_glprogram )
{
return;
} glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
m_glprogram->use();
m_glprogram->setUniformsForBuiltins(); Size sSize = Director::getInstance()->getVisibleSize();
float x = ;
float y = ;
float w = sSize.width;
float h = sSize.height; // 除当前纹理外的纹理存储的都是拖影
int nBeginIndex = m_nCurTexutreIndex;
int nCurIndex = nBeginIndex;
GLfloat falpha = 0.3f;
float addf = 0.05f; // 渲染存在m_pTextureArr队列里的拖影纹理到主场景
do
{
Point delta = _position;// this->convertToWorldSpace(_position);
GLfloat vertices[] = {
x - delta.x,y+ h - delta.y,
x+w - delta.x,y+ h - delta.y,
x - delta.x , y - delta.y,
x+w - delta.x, y - delta.y
};
//GLuint glTexture = m_glprogram->getUniformLocationForName("CC_Texture0");
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, m_pTextureArr[nCurIndex]);
//glUniform1i(glTexture, 0);
GL::bindTexture2D(m_pTextureArr[nCurIndex]); GLuint glAlpha = m_glprogram->getUniformLocationForName("u_alpha");
glUniform1f(glAlpha, falpha); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, , GL_FLOAT, GL_FALSE, , ccRenderTextcord);
glDrawArrays(GL_TRIANGLE_STRIP, , ); falpha += addf;
addf += 0.025f;
nCurIndex = ++nCurIndex<REMIND_RENDER_COUNT ? nCurIndex : ;
} while (nCurIndex != nBeginIndex);
//
// GL::bindVAO(0);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void RemindShader::CreateFrameBuffer()
{ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
if (m_nFrameBuffer == )
{
glGenFramebuffers(, &m_nFrameBuffer); if (m_nFrameBuffer == )
{
CCLOG("m_FilterFrameBuffer == 0");
return;
}
}
GLsizei nWidth = m_sRenderSize.width;
GLsizei nHeight = m_sRenderSize.height;
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
if (m_pTextureArr[] == )
{
glGenTextures(REMIND_RENDER_COUNT, m_pTextureArr);
for (int i = ; i < REMIND_RENDER_COUNT; i++)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_pTextureArr[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, nWidth, nHeight, , GL_RGBA, GL_UNSIGNED_BYTE, );
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
CCLOG("cocos2d: Texture2D: Error uploading compressed texture glError: 0x%04X", err);
return;
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureArr[i], );
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
} void RemindShader::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
if (sRenderChild.size() <= )
{
if (m_nFrameBuffer)
{
// 清理所有缓存的纹理
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nOldFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_nFrameBuffer);
for (int i = ; i < REMIND_RENDER_COUNT; i++)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTextureArr[i], );
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
glBindFramebuffer(GL_FRAMEBUFFER, m_nOldFBO);
}
m_nRenderCount = m_nRenderFrq - ;
return;
}
//Begin will create a render group using new render target
begin(); if (++m_nRenderCount == m_nRenderFrq)
{
//! make sure all children are drawn
auto it = sRenderChild.begin();
while (it != sRenderChild.end())
{
if (Node* node = *it)
{
node->visit(renderer, transform, flags);
node->release();
}
++it;
}
m_nRenderCount = ; // 0 提示需要渲染进去
}
sRenderChild.clear();
//End will pop the current render group
end(); }

几个关键点:

1、利用REMIND_RENDER_COUNT控制需要创建的Texture个数,通过每次绘制到不同的Texture上来保存原来的效果。

2、shader中利用u_alpha参数控制残影的透明度,在render中绘制到原来的FBO上时调用不同的透明度来实现残影渐隐的效果。

3、通过m_nRenderFrq来控制间隔的绘制次数,来实现残影的残留效果远近。

这样就实现了残影的效果了,使用的方法还是跟基类一样。

完整代码地址:https://github.com/mydishes/cocos2dx-Ex/tree/master/Shader

cocos2dx - shader实现任意动画的残影效果的更多相关文章

  1. Unity3D手游开发日记(8) - 运动残影效果

    2D游戏的残影很简单,美术做序列帧图片就行了,那么3D游戏的残影美术做不了,得靠程序员动态创建模型来处理. 实现原理也很简单: 1.间隔一定时间创建一个残影模型 GameObject go = Gam ...

  2. Unity3D-Shader-人物残影效果

    [旧博客转移 - 2016年1月7日 00:24 ] 前面的话 上一篇讲了一下人物边缘发光效果,链接: Unity-ShaderLab-实现X光效果,这次我们利用这个Shader来实现人物残影效果 先 ...

  3. as3如何做出残影效果

    在页游中,时不时能看到人物做一些快速移动动作如冲刺时,有残影效果,强化了画面表现.实际人肉眼之所以能看到残影的效果,是因为观察到的物体会在人视线中残留几十毫秒时间,当运动物体运动太快时,人肉眼所见未能 ...

  4. Unity3d 残影效果(狂拽炫酷叼炸天)

    效果图,真的很叼啊 我根据别人的改进了一版,支持MeshFilter上的Mesh(需要确保Mesh的Read/Write是开启的否则不能正常工作) 非常感谢原作者给提供思路.http://blog.c ...

  5. Unity Shader : Ghost(残影) v1

    前阵子组长给我提了个需求,要实现角色人物的残影.我百度google了一下,发现可以用两种方式实现这个效果:1.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染.2. 通过相 ...

  6. Unity运动残影技能

    残影实现: 1.List<DrawMesh> list,此list中包含某一帧动画模型网格.材质 2.每过一段时间就将运动物体的模型add到list中(优化:未实现,网格合并) 3.Lat ...

  7. PS制作gif动图以及背景透明与消除残影

    摘要: 用Photoshop制作gif动画的要点:在窗口菜单中找到“时间轴”选中打开时间轴,单击一帧,设置该帧显示持续时间在图层里将该帧要显示的图层显示,并将不该显示的层隐藏,新建一帧,接下来就是重复 ...

  8. Win7去除桌面残影的方法

    用户升级到Win7系统后使用正常,就是系统桌面会留有残影,怎么样也去不掉,影响用户的使用,那么要如何将这些残影去掉呢?可从计算机属性中进行相关配置. 解决方法 一.在计算机面板上,右键点击“计算机”, ...

  9. HDOJ(HDU) 2153 仙人球的残影(谜一样的题、、、)

    Problem Description 在美丽的HDU,有一名大三的同学,他的速度是众所周知的,跑100米仅仅用了2秒47,在他跑步过程中会留下残影的哎,大家很想知道他是谁了吧,他叫仙人球,既然名字这 ...

随机推荐

  1. 201521123035《Java程序设计》第八周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 //泛型方法,打印MyStack的所有元素的薪水,不管MyStack中 ...

  2. 201521123051《Java程序设计》第六周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  3. 201521123020 《Java程序设计》第6周学习总结

    本周学习总结 书面作业 1.clone方法 1.1 Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么? 答:需要将protected改为pu ...

  4. 201521123067《Java程序设计》第1周学习总结

    1.本周学习总结 在本周的java学习中,我知道了java的发展历程,JDK和JRE以及JVM的区别与联系,并学习了如何安装Eclipse和搭建java的环境,编写出了第一个java程序,明白了jav ...

  5. 201521123064 《Java程序设计》第14周学习总结

    本次作业参考文件 数据库PPT MySql操作视频与数据库相关jar文件请参考QQ群文件. 1. 本章学习总结 1.1 以你喜欢的方式(思维导图.OneNote或其他)归纳总结数据库相关内容. 1.数 ...

  6. 201521123103 《java学习笔记》 第十四周学习总结

    一.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 二.书面作业 1. MySQL数据库基本操作 1.1建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现 ...

  7. 201521123023《Java程序设计》第14周学习总结

    1. 本周学习总结 (1)ResultSet.Statement.Connection使用完后最好立刻关闭,并且按照ResultSet.Statement.Connection的顺序依次关闭. (2) ...

  8. Install Oracle 12c R2 on CentOS 7 silent

    准备工作 VMware 虚拟机 CentOS 7 17.08 系统安装包镜像 Oracle 12c R2 软件安装包 配置 yum 库并安装如下包 binutils-2.23.52.0.1-12.el ...

  9. 泛型在Web中的作用

    当我们写网页的时候,常常会有多个DAO,我们要写每次都要写好几个DAO,这样会有点麻烦. 那么我们想要的效果是什么呢??只写一个抽象DAO,别的DAO只要继承该抽象DAO,就有对应的方法了. 要实现这 ...

  10. CSS1-3基礎知識

    CSS1-3基礎知識 1.css排版 css在html內排版: <style type='text/css'> 標記名{} .類型名{} #ID名{} 標記名,.類型名,#ID名{} &l ...